stxxl-1.3.1/0000755000175000017500000000000011536252421012513 5ustar andreasandreasstxxl-1.3.1/config_example0000644000175000017500000000052410622615152015416 0ustar andreasandreasdisk=/mnt/hdc/stxxl,70000,syscall disk=/mnt/hde/stxxl,70000,syscall disk=/mnt/hdg/stxxl,70000,syscall disk=/mnt/hdi/stxxl,70000,syscall disk=/mnt/hdm/stxxl,70000,syscall disk=/mnt/hdo/stxxl,70000,syscall disk=/mnt/hdq/stxxl,70000,syscall disk=/mnt/hds/stxxl,70000,syscall disk=/mnt/hdu/stxxl,70000,syscall disk=/mnt/hdw/stxxl,70000,syscall stxxl-1.3.1/mng/0000755000175000017500000000000011536252420013273 5ustar andreasandreasstxxl-1.3.1/mng/test_mng1.cpp0000644000175000017500000000246611535500414015706 0ustar andreasandreas/*************************************************************************** * mng/test_mng1.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2002 Roman Dementiev * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #include #include int main() { typedef stxxl::typed_block<128 * 1024, double> block_type; std::vector bids; std::vector requests; stxxl::block_manager * bm = stxxl::block_manager::get_instance(); bm->new_blocks(32, stxxl::striping(), std::back_inserter(bids)); std::vector > blocks(32); int vIndex; for (vIndex = 0; vIndex < 32; ++vIndex) { for (int vIndex2 = 0; vIndex2 < block_type::size; ++vIndex2) { blocks[vIndex][vIndex2] = vIndex2; } } for (vIndex = 0; vIndex < 32; ++vIndex) { requests.push_back(blocks[vIndex].write(bids[vIndex])); } stxxl::wait_all(requests.begin(), requests.end()); bm->delete_blocks(bids.begin(), bids.end()); return 0; } stxxl-1.3.1/mng/test_aligned.cpp0000644000175000017500000000352411260636771016456 0ustar andreasandreas/*************************************************************************** * mng/test_aligned.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2009 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #define STXXL_VERBOSE_LEVEL 0 #define STXXL_VERBOSE_ALIGNED_ALLOC STXXL_VERBOSE0 #define STXXL_VERBOSE_TYPED_BLOCK STXXL_VERBOSE0 #include #include #include #define BLOCK_SIZE (1024 * 1024) struct type { int i; ~type() { } }; typedef stxxl::typed_block block_type; void test_typed_block() { block_type * a = new block_type; block_type * b = new block_type; block_type * A = new block_type[4]; block_type * B = new block_type[1]; block_type * C = NULL; //C = new block_type[0]; delete a; a = b; b = 0; delete b; delete a; delete[] A; delete[] B; delete[] C; } void test_aligned_alloc() { void * p = stxxl::aligned_alloc<1024>(4096); void * q = NULL; void * r = stxxl::aligned_alloc<1024>(4096, 42); stxxl::aligned_dealloc<1024>(p); stxxl::aligned_dealloc<1024>(q); stxxl::aligned_dealloc<1024>(r); } void test_typed_block_vector() { std::vector v1(2); std::vector > v2(2); } int main() { try { test_typed_block(); test_aligned_alloc(); test_typed_block_vector(); } catch (std::exception e) { STXXL_MSG("OOPS: " << e.what()); return 1; } catch (char const * c) { STXXL_MSG("OOPS: " << c); return 1; } } // vim: et:ts=4:sw=4 stxxl-1.3.1/mng/config.cpp0000644000175000017500000000746411535507175015270 0ustar andreasandreas/*************************************************************************** * mng/config.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2002 Roman Dementiev * Copyright (C) 2007, 2009 Johannes Singler * Copyright (C) 2008, 2009 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #include #include #include #include #include #ifdef BOOST_MSVC #include #endif __STXXL_BEGIN_NAMESPACE void config::init(const char * config_path) { logger::get_instance(); STXXL_MSG(get_version_string()); std::vector flash_props; std::ifstream cfg_file(config_path); if (!cfg_file) { STXXL_ERRMSG("Warning: no config file found."); STXXL_ERRMSG("Using default disk configuration."); #ifndef BOOST_MSVC DiskEntry entry1 = { "/var/tmp/stxxl", "syscall", 1000 * 1024 * 1024, true, false }; #else DiskEntry entry1 = { "", "wincall", 1000 * 1024 * 1024, true, false }; char * tmpstr = new char[255]; stxxl_check_ne_0(GetTempPath(255, tmpstr), resource_error); entry1.path = tmpstr; entry1.path += "stxxl"; delete[] tmpstr; #endif #if 0 DiskEntry entry2 = { "/tmp/stxxl1", "mmap", 100 * 1024 * 1024, true }; DiskEntry entry3 = { "/tmp/stxxl2", "simdisk", 1000 * 1024 * 1024, false }; #endif disks_props.push_back(entry1); //disks_props.push_back(entry2); //disks_props.push_back(entry3); } else { std::string line; while (cfg_file >> line) { std::vector tmp = split(line, "="); bool is_disk; if (tmp[0][0] == '#') { } else if ((is_disk = (tmp[0] == "disk")) || tmp[0] == "flash") { tmp = split(tmp[1], ","); DiskEntry entry = { tmp[0], tmp[2], int64(atoi(tmp[1].c_str())) * int64(1024 * 1024), false, false }; if (entry.size == 0) entry.autogrow = true; if (is_disk) disks_props.push_back(entry); else flash_props.push_back(entry); } else { std::cerr << "Unknown token " << tmp[0] << std::endl; } } cfg_file.close(); } // put flash devices after regular disks first_flash = disks_props.size(); disks_props.insert(disks_props.end(), flash_props.begin(), flash_props.end()); if (disks_props.empty()) STXXL_THROW(std::runtime_error, "config::config", "No disks found in '" << config_path << "' ."); #ifdef STXXL_VERBOSE_DISKS for (std::vector::const_iterator it = disks_props.begin(); it != disks_props.end(); it++) { STXXL_MSG("Disk '" << (*it).path << "' is allocated, space: " << ((*it).size) / (1024 * 1024) << " MiB, I/O implementation: " << (*it).io_impl); } #else int64 total_size = 0; for (std::vector::const_iterator it = disks_props.begin(); it != disks_props.end(); it++) total_size += (*it).size; STXXL_MSG("" << disks_props.size() << " disks are allocated, total space: " << (total_size / (1024 * 1024)) << " MiB"); #endif } __STXXL_END_NAMESPACE // vim: et:ts=4:sw=4 stxxl-1.3.1/mng/GNUmakefile0000644000175000017500000000205411421035471015344 0ustar andreasandreasTOPDIR ?= .. include Makefile.common -include $(TOPDIR)/make.settings.local ENABLE_UNITTEST ?= no TESTS-yes += $(TESTS_NON_MSVC) TESTS-$(ENABLE_UNITTEST) += $(TESTS_UNITTEST) include $(TOPDIR)/Makefile.subdir.gnu # requires libcppunit-dev to be installed unittest.$o: CPPFLAGS += $(CPPUNIT_COMPILER_OPTIONS) unittest.$(bin): STXXL_LINKER_OPTIONS += $(CPPUNIT_LINKER_OPTIONS) test_mng.$o: CPPFLAGS += -DSTXXL_VERBOSE_LEVEL=2 test_mng1.$o: CPPFLAGS += -DSTXXL_VERBOSE_LEVEL=2 test_write_pool.$o: CPPFLAGS += -DSTXXL_VERBOSE_LEVEL=1 test_prefetch_pool.$o: CPPFLAGS += -DSTXXL_VERBOSE_LEVEL=2 test_mng_recursive_alloc.$o: CPPFLAGS += -DSTXXL_VERBOSE_LEVEL=3 test_aligned.$o: OPT_LEVEL = 0 ifeq ($(strip $(USE_MCSTL)),yes) # ICPC 11.0: internal error: 0_1374 (issue 539748) $(call reduce_optimization,3,0,test_block_alloc_strategy,Version_11.0,any,any) # ICPC 10.0: internal error: backend signals (issue 466173) $(call reduce_optimization,3,1,test_buf_streams,Version_10.0,32-bit,any) $(call reduce_optimization,3,1,unittest,Version_10.0,32-bit,any) endif stxxl-1.3.1/mng/test_buf_streams.cpp0000644000175000017500000000346611037133765017367 0ustar andreasandreas/*************************************************************************** * mng/test_buf_streams.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2002 Roman Dementiev * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ //! \example mng/test_buf_streams.cpp //! This is an example of use of \c stxxl::buf_istream and \c stxxl::buf_ostream #include #include #include #include #define BLOCK_SIZE (1024 * 512) typedef stxxl::typed_block block_type; typedef stxxl::buf_ostream::iterator> buf_ostream_type; typedef stxxl::buf_istream::iterator> buf_istream_type; int main() { const unsigned nblocks = 64; const unsigned nelements = nblocks * block_type::size; stxxl::BIDArray bids(nblocks); stxxl::block_manager * bm = stxxl::block_manager::get_instance(); bm->new_blocks(stxxl::striping(), bids.begin(), bids.end()); { buf_ostream_type out(bids.begin(), 2); for (unsigned i = 0; i < nelements; i++) out << i; } { buf_istream_type in(bids.begin(), bids.end(), 2); for (unsigned i = 0; i < nelements; i++) { unsigned value; in >> value; if (value != i) { STXXL_ERRMSG("Error at position " << std::hex << i << " (" << value << ") block " << (i / block_type::size)); } } } bm->delete_blocks(bids.begin(), bids.end()); } stxxl-1.3.1/mng/test_read_write_pool.cpp0000644000175000017500000000651711254226655020235 0ustar andreasandreas/*************************************************************************** * mng/test_read_write_pool.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2009 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ //! \example mng/test_read_write_pool.cpp #include #include #include #define BLOCK_SIZE (1024 * 512) struct MyType { int integer; char chars[5]; }; typedef stxxl::typed_block block_type; int main() { stxxl::block_manager * bm = stxxl::block_manager::get_instance(); STXXL_DEFAULT_ALLOC_STRATEGY alloc; { STXXL_MSG("Write-After-Write coherence test"); stxxl::read_write_pool pool(2, 10); block_type * blk; block_type::bid_type bid; bm->new_block(alloc, bid); // write the block for the first time blk = pool.steal(); (*blk)[0].integer = 42; pool.write(blk, bid); // read the block blk = pool.steal(); pool.read(blk, bid)->wait(); delete blk; // write the block for the second time blk = pool.steal(); (*blk)[0].integer = 23; pool.write(blk, bid); // hint the block pool.hint(bid); // flush w_pool // get the hinted block blk = pool.steal(); pool.read(blk, bid)->wait(); if ((*blk)[0].integer != 23) { STXXL_ERRMSG("WRITE-AFTER-WRITE COHERENCE FAILURE"); } pool.add(blk); bm->delete_block(bid); } { STXXL_MSG("Write-After-Hint coherence test #1"); stxxl::read_write_pool pool(1, 1); block_type * blk; block_type::bid_type bid; bm->new_block(alloc, bid); blk = pool.steal(); (*blk)[0].integer = 42; pool.write(blk, bid); blk = pool.steal(); // flush w_pool // hint the block pool.hint(bid); // update the hinted block (*blk)[0].integer = 23; pool.write(blk, bid); blk = pool.steal(); // flush w_pool // get the hinted block pool.read(blk, bid)->wait(); if ((*blk)[0].integer != 23) { STXXL_ERRMSG("WRITE-AFTER-HINT COHERENCE FAILURE"); } pool.add(blk); bm->delete_block(bid); } { STXXL_MSG("Write-After-Hint coherence test #2"); stxxl::read_write_pool pool(1, 1); block_type * blk; block_type::bid_type bid; bm->new_block(alloc, bid); blk = pool.steal(); (*blk)[0].integer = 42; pool.write(blk, bid); // hint the block pool.hint(bid); // update the hinted block blk = pool.steal(); (*blk)[0].integer = 23; pool.write(blk, bid); blk = pool.steal(); // flush w_pool // get the hinted block pool.read(blk, bid)->wait(); if ((*blk)[0].integer != 23) { STXXL_ERRMSG("WRITE-AFTER-HINT COHERENCE FAILURE"); } pool.add(blk); bm->delete_block(bid); } } // vim: et:ts=4:sw=4 stxxl-1.3.1/mng/unittest.cpp0000644000175000017500000001314211535151017015656 0ustar andreasandreas/*************************************************************************** * mng/unittest.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2007 Roman Dementiev * Copyright (C) 2009 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #include #include #include #include #include #define BLOCK_SIZE (1024 * 512) struct MyType { int integer; char chars[5]; }; struct my_handler { void operator () (stxxl::request * req) { STXXL_MSG(req << " done, type=" << req->io_type()); } }; typedef stxxl::typed_block block_type; class BMLayerTest : public CppUnit::TestCase { CPPUNIT_TEST_SUITE(BMLayerTest); CPPUNIT_TEST(testIO); CPPUNIT_TEST(testIO2); CPPUNIT_TEST(testPrefetchPool); CPPUNIT_TEST(testWritePool); CPPUNIT_TEST(testStreams); CPPUNIT_TEST_SUITE_END(); public: BMLayerTest(std::string name) : CppUnit::TestCase(name) { } BMLayerTest() { } void testIO() { const unsigned nblocks = 2; stxxl::BIDArray bids(nblocks); std::vector disks(nblocks, 2); stxxl::request_ptr * reqs = new stxxl::request_ptr[nblocks]; stxxl::block_manager * bm = stxxl::block_manager::get_instance(); bm->new_blocks(stxxl::striping(), bids.begin(), bids.end()); block_type * block = new block_type; STXXL_MSG(std::hex); STXXL_MSG("Allocated block address : " << long(block)); STXXL_MSG("Allocated block address + 1: " << long(block + 1)); STXXL_MSG(std::dec); unsigned i = 0; for (i = 0; i < block_type::size; ++i) { block->elem[i].integer = i; //memcpy (block->elem[i].chars, "STXXL", 4); } for (i = 0; i < nblocks; ++i) reqs[i] = block->write(bids[i], my_handler()); std::cout << "Waiting " << std::endl; stxxl::wait_all(reqs, nblocks); for (i = 0; i < nblocks; ++i) { reqs[i] = block->read(bids[i], my_handler()); reqs[i]->wait(); for (int j = 0; j < block_type::size; ++j) { CPPUNIT_ASSERT(j == block->elem[j].integer); } } bm->delete_blocks(bids.begin(), bids.end()); delete[] reqs; delete block; } void testIO2() { typedef stxxl::typed_block<128 * 1024, double> block_type; std::vector bids; std::vector requests; stxxl::block_manager * bm = stxxl::block_manager::get_instance(); bm->new_blocks(32, stxxl::striping(), std::back_inserter(bids)); block_type * blocks = new block_type[32]; int vIndex; for (vIndex = 0; vIndex < 32; ++vIndex) { for (int vIndex2 = 0; vIndex2 < block_type::size; ++vIndex2) { blocks[vIndex][vIndex2] = vIndex2; } } for (vIndex = 0; vIndex < 32; ++vIndex) { requests.push_back(blocks[vIndex].write(bids[vIndex])); } stxxl::wait_all(requests.begin(), requests.end()); bm->delete_blocks(bids.begin(), bids.end()); delete[] blocks; } void testPrefetchPool() { stxxl::prefetch_pool pool(2); pool.resize(10); pool.resize(5); block_type * blk = new block_type; block_type::bid_type bid; stxxl::block_manager::get_instance()->new_block(stxxl::single_disk(), bid); pool.hint(bid); pool.read(blk, bid)->wait(); delete blk; } void testWritePool() { stxxl::write_pool pool(100); pool.resize(10); pool.resize(5); block_type * blk = new block_type; block_type::bid_type bid; stxxl::block_manager::get_instance()->new_block(stxxl::single_disk(), bid); pool.write(blk, bid); } typedef stxxl::typed_block block_type1; typedef stxxl::buf_ostream::iterator> buf_ostream_type; typedef stxxl::buf_istream::iterator> buf_istream_type; void testStreams() { const unsigned nblocks = 64; const unsigned nelements = nblocks * block_type1::size; stxxl::BIDArray bids(nblocks); stxxl::block_manager * bm = stxxl::block_manager::get_instance(); bm->new_blocks(stxxl::striping(), bids.begin(), bids.end()); { buf_ostream_type out(bids.begin(), 2); for (unsigned i = 0; i < nelements; i++) out << i; } { buf_istream_type in(bids.begin(), bids.end(), 2); for (unsigned i = 0; i < nelements; i++) { int value; in >> value; CPPUNIT_ASSERT(value == int(i)); } } bm->delete_blocks(bids.begin(), bids.end()); } }; CPPUNIT_TEST_SUITE_REGISTRATION(BMLayerTest); int main() { CppUnit::TextUi::TestRunner runner; CppUnit::TestFactoryRegistry & registry = CppUnit::TestFactoryRegistry::getRegistry(); runner.addTest(registry.makeTest()); bool wasSuccessful = runner.run("", false); return wasSuccessful ? 0 : 1; } stxxl-1.3.1/mng/test_mng.cpp0000644000175000017500000000557611535500414015632 0ustar andreasandreas/*************************************************************************** * mng/test_mng.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2002 Roman Dementiev * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ //! \example mng/test_mng.cpp //! This is an example of use of completion handlers, \c stxxl::block_manager, and //! \c stxxl::typed_block #include #include #include #define BLOCK_SIZE (1024 * 512) struct MyType { int integer; //char chars[4]; ~MyType() { } }; struct my_handler { void operator () (stxxl::request * req) { STXXL_MSG(req << " done, type=" << req->io_type()); } }; typedef stxxl::typed_block block_type; int main() { STXXL_MSG(sizeof(MyType) << " " << (BLOCK_SIZE % sizeof(MyType))); STXXL_MSG(sizeof(block_type) << " " << BLOCK_SIZE); const unsigned nblocks = 2; stxxl::BIDArray bids(nblocks); std::vector disks(nblocks, 2); stxxl::request_ptr * reqs = new stxxl::request_ptr[nblocks]; stxxl::block_manager * bm = stxxl::block_manager::get_instance(); bm->new_blocks(stxxl::striping(), bids.begin(), bids.end()); block_type * block = new block_type[2]; STXXL_MSG(std::hex); STXXL_MSG("Allocated block address : " << long(block)); STXXL_MSG("Allocated block address + 1: " << long(block + 1)); STXXL_MSG(std::dec); unsigned i = 0; for (i = 0; i < block_type::size; ++i) { block->elem[i].integer = i; //memcpy (block->elem[i].chars, "STXXL", 4); } for (i = 0; i < nblocks; ++i) reqs[i] = block->write(bids[i], my_handler()); std::cout << "Waiting " << std::endl; stxxl::wait_all(reqs, nblocks); for (i = 0; i < nblocks; ++i) { reqs[i] = block->read(bids[i], my_handler()); reqs[i]->wait(); for (int j = 0; j < block_type::size; ++j) { if (j != block->elem[j].integer) { STXXL_MSG("Error in block " << std::hex << i << " pos: " << j << " value read: " << block->elem[j].integer); } } } bm->delete_blocks(bids.begin(), bids.end()); delete[] reqs; delete[] block; #if 0 // variable-size blocks, not supported currently BIDArray<0> vbids(nblocks); for (i = 0; i < nblocks; i++) vbids[i].size = 1024 + i; bm->new_blocks(striping(), vbids.begin(), vbids.end()); for (i = 0; i < nblocks; i++) STXXL_MSG("Allocated block: offset=" << vbids[i].offset << ", size=" << vbids[i].size); bm->delete_blocks(vbids.begin(), vbids.end()); #endif } stxxl-1.3.1/mng/mng.cpp0000644000175000017500000000305011513611117014553 0ustar andreasandreas/*************************************************************************** * mng/mng.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2002-2004 Roman Dementiev * Copyright (C) 2008, 2010 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #include __STXXL_BEGIN_NAMESPACE block_manager::block_manager() { config * cfg = config::get_instance(); ndisks = cfg->disks_number(); disk_allocators = new DiskAllocator *[ndisks]; disk_files = new file *[ndisks]; for (unsigned i = 0; i < ndisks; ++i) { disk_files[i] = create_file(cfg->disk_io_impl(i), cfg->disk_path(i), file::CREAT | file::RDWR | file::DIRECT, i, // physical_device_id i); // allocator_id disk_allocators[i] = new DiskAllocator(disk_files[i], cfg->disk_size(i)); } } block_manager::~block_manager() { STXXL_VERBOSE1("Block manager destructor"); for (unsigned i = ndisks; i > 0; ) { --i; delete disk_allocators[i]; delete disk_files[i]; } delete[] disk_allocators; delete[] disk_files; } __STXXL_END_NAMESPACE // vim: et:ts=4:sw=4 stxxl-1.3.1/mng/test_mng_recursive_alloc.cpp0000644000175000017500000000417311050267016021063 0ustar andreasandreas/*************************************************************************** * mng/test_mng_recursive_alloc.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2008 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #include #include #define BLOCK_SIZE (1024 * 1024 * 32) typedef stxxl::typed_block block_type; int main() { unsigned i; stxxl::int64 totalsize = 0; stxxl::config * config = stxxl::config::get_instance(); for (i = 0; i < config->disks_number(); ++i) totalsize += config->disk_size(i); stxxl::unsigned_type totalblocks = totalsize / block_type::raw_size; STXXL_MSG("external memory: " << totalsize << " bytes == " << totalblocks << " blocks"); stxxl::BIDArray b5a(totalblocks / 5); stxxl::BIDArray b5b(totalblocks / 5); stxxl::BIDArray b5c(totalblocks / 5); stxxl::BIDArray b5d(totalblocks / 5); stxxl::BIDArray b2(totalblocks / 2); stxxl::block_manager * bm = stxxl::block_manager::get_instance(); STXXL_MSG("get 4 x " << totalblocks / 5); bm->new_blocks(stxxl::striping(), b5a.begin(), b5a.end()); bm->new_blocks(stxxl::striping(), b5b.begin(), b5b.end()); bm->new_blocks(stxxl::striping(), b5c.begin(), b5c.end()); bm->new_blocks(stxxl::striping(), b5d.begin(), b5d.end()); STXXL_MSG("free 2 x " << totalblocks / 5); bm->delete_blocks(b5a.begin(), b5a.end()); bm->delete_blocks(b5c.begin(), b5c.end()); // the external memory should now be fragmented enough, // s.t. the following request needs to be split into smaller ones STXXL_MSG("get 1 x " << totalblocks / 2); bm->new_blocks(stxxl::striping(), b2.begin(), b2.end()); bm->delete_blocks(b5b.begin(), b5b.end()); bm->delete_blocks(b5d.begin(), b5d.end()); bm->delete_blocks(b2.begin(), b2.end()); } stxxl-1.3.1/mng/test_write_pool.cpp0000644000175000017500000000212711535151017017222 0ustar andreasandreas/*************************************************************************** * mng/test_write_pool.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2003 Roman Dementiev * Copyright (C) 2009 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ //! \example mng/test_write_pool.cpp #include #include #include #define BLOCK_SIZE (1024 * 512) struct MyType { int integer; char chars[5]; }; typedef stxxl::typed_block block_type; int main() { stxxl::write_pool pool(100); pool.resize(10); pool.resize(5); block_type * blk = new block_type; block_type::bid_type bid; stxxl::block_manager::get_instance()->new_block(stxxl::single_disk(), bid); pool.write(blk, bid)->wait(); delete blk; } stxxl-1.3.1/mng/Makefile.common0000644000175000017500000000043011463030034016211 0ustar andreasandreasTESTS = test_mng test_mng1 test_buf_streams test_write_pool test_prefetch_pool test_block_alloc_strategy test_mng_recursive_alloc test_pool_pair test_read_write_pool test_aligned TESTS_NON_MSVC = TESTS_UNITTEST = unittest LIB_SRC = config.cpp mng.cpp diskallocator.cpp stxxl-1.3.1/mng/test_pool_pair.cpp0000644000175000017500000000720611254226655017037 0ustar andreasandreas/*************************************************************************** * mng/test_pool_pair.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2009 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ //! \example mng/test_pool_pair.cpp #include #include #include #include #define BLOCK_SIZE (1024 * 512) struct MyType { int integer; char chars[5]; }; typedef stxxl::typed_block block_type; int main() { stxxl::block_manager * bm = stxxl::block_manager::get_instance(); STXXL_DEFAULT_ALLOC_STRATEGY alloc; { STXXL_MSG("Write-After-Write coherence test"); stxxl::prefetch_pool p_pool(2); stxxl::write_pool w_pool(10); block_type * blk; block_type::bid_type bid; bm->new_block(alloc, bid); // write the block for the first time blk = w_pool.steal(); (*blk)[0].integer = 42; w_pool.write(blk, bid); // read the block blk = w_pool.steal(); p_pool.read(blk, bid)->wait(); delete blk; // write the block for the second time blk = w_pool.steal(); (*blk)[0].integer = 23; w_pool.write(blk, bid); // hint the block p_pool.hint(bid, w_pool); // flush w_pool // get the hinted block blk = w_pool.steal(); p_pool.read(blk, bid)->wait(); if ((*blk)[0].integer != 23) { STXXL_ERRMSG("WRITE-AFTER-WRITE COHERENCE FAILURE"); } w_pool.add(blk); bm->delete_block(bid); } { STXXL_MSG("Write-After-Hint coherence test #1"); stxxl::prefetch_pool p_pool(1); stxxl::write_pool w_pool(1); block_type * blk; block_type::bid_type bid; bm->new_block(alloc, bid); blk = w_pool.steal(); (*blk)[0].integer = 42; w_pool.write(blk, bid); blk = w_pool.steal(); // flush w_pool // hint the block p_pool.hint(bid); // update the hinted block (*blk)[0].integer = 23; w_pool.write(blk, bid); p_pool.invalidate(bid); blk = w_pool.steal(); // flush w_pool // get the hinted block p_pool.read(blk, bid)->wait(); if ((*blk)[0].integer != 23) { STXXL_ERRMSG("WRITE-AFTER-HINT COHERENCE FAILURE"); } w_pool.add(blk); bm->delete_block(bid); } { STXXL_MSG("Write-After-Hint coherence test #2"); stxxl::prefetch_pool p_pool(1); stxxl::write_pool w_pool(1); block_type * blk; block_type::bid_type bid; bm->new_block(alloc, bid); blk = w_pool.steal(); (*blk)[0].integer = 42; w_pool.write(blk, bid); // hint the block p_pool.hint(bid, w_pool); // flush w_pool // update the hinted block blk = w_pool.steal(); (*blk)[0].integer = 23; w_pool.write(blk, bid); p_pool.invalidate(bid); blk = w_pool.steal(); // flush w_pool // get the hinted block p_pool.read(blk, bid)->wait(); if ((*blk)[0].integer != 23) { STXXL_ERRMSG("WRITE-AFTER-HINT COHERENCE FAILURE"); } w_pool.add(blk); bm->delete_block(bid); } } // vim: et:ts=4:sw=4 stxxl-1.3.1/mng/test_block_alloc_strategy.cpp0000644000175000017500000000467311535513725021245 0ustar andreasandreas/*************************************************************************** * mng/test_block_alloc_strategy.cpp * * instantiate all block allocation strategies * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright © 2008 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #include #include #include template void test_strategy() { STXXL_MSG(STXXL_PRETTY_FUNCTION_NAME); strategy s0; strategy s2(1, 3); stxxl::offset_allocator o(1, s0); typedef typename stxxl::interleaved_alloc_traits::strategy interleaved; interleaved itl(23, strategy(1, 3)); for (int i = 0; i < 16; ++i) STXXL_MSG(s0(i) << " " << s2(i) << " " << o(i) << " " << itl(i)); int firstdisk = 0; int ndisks = 4; int nruns = 10; int runsize = 15; std::cout << "firstdisk=" << firstdisk << " ndisks=" << ndisks << " nruns=" << nruns << " runsize=" << runsize; interleaved itl2(nruns, strategy(firstdisk, firstdisk + ndisks)); for (int i = 0; i < nruns * runsize; ++i) { if (i % nruns == 0) std::cout << std::endl; std::cout << itl2(i) << " "; } std::cout << std::endl; } int main() { stxxl::config * cfg = stxxl::config::get_instance(); // instantiate the allocation strategies STXXL_MSG("Number of disks: " << cfg->disks_number()); for (unsigned i = 0; i < cfg->disks_number(); ++i) STXXL_MSG(cfg->disk_path(i) << ", " << cfg->disk_size(i) << ", " << cfg->disk_io_impl(i)); test_strategy(); test_strategy(); test_strategy(); test_strategy(); STXXL_MSG("Regular disks: [" << cfg->regular_disk_range().first << "," << cfg->regular_disk_range().second << ")"); if (cfg->regular_disk_range().first != cfg->regular_disk_range().second) test_strategy(); STXXL_MSG("Flash devices: [" << cfg->flash_range().first << "," << cfg->flash_range().second << ")"); if (cfg->flash_range().first != cfg->flash_range().second) test_strategy(); test_strategy(); } stxxl-1.3.1/mng/test_prefetch_pool.cpp0000644000175000017500000000242211531445437017676 0ustar andreasandreas/*************************************************************************** * mng/test_prefetch_pool.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2003 Roman Dementiev * Copyright (C) 2009 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ //! \example mng/test_prefetch_pool.cpp #include #include #include #define BLOCK_SIZE (1024 * 512) struct MyType { int integer; char chars[5]; }; typedef stxxl::typed_block block_type; int main() { stxxl::prefetch_pool pool(2); pool.resize(10); pool.resize(5); block_type * blk = new block_type; (*blk)[0].integer = 42; block_type::bid_type bids[2]; stxxl::block_manager::get_instance()->new_blocks(stxxl::single_disk(), bids, bids + 2); blk->write(bids[0])->wait(); blk->write(bids[1])->wait(); pool.hint(bids[0]); pool.read(blk, bids[0])->wait(); pool.read(blk, bids[1])->wait(); delete blk; } stxxl-1.3.1/mng/diskallocator.cpp0000644000175000017500000001262511535507175016651 0ustar andreasandreas/*************************************************************************** * mng/diskallocator.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2002 Roman Dementiev * Copyright (C) 2008, 2010 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #include #include __STXXL_BEGIN_NAMESPACE void DiskAllocator::dump() const { int64 total = 0; sortseq::const_iterator cur = free_space.begin(); STXXL_ERRMSG("Free regions dump:"); for ( ; cur != free_space.end(); ++cur) { STXXL_ERRMSG("Free chunk: begin: " << (cur->first) << " size: " << (cur->second)); total += cur->second; } STXXL_ERRMSG("Total bytes: " << total); } void DiskAllocator::deallocation_error( stxxl::int64 block_pos, stxxl::int64 block_size, const sortseq::iterator & pred, const sortseq::iterator & succ) const { STXXL_ERRMSG("Error deallocating block at " << block_pos << " size " << block_size); STXXL_ERRMSG(((pred == succ) ? "pred==succ" : "pred!=succ")); if (pred == free_space.end()) { STXXL_ERRMSG("pred==free_space.end()"); } else { if (pred == free_space.begin()) STXXL_ERRMSG("pred==free_space.begin()"); STXXL_ERRMSG("pred: begin=" << pred->first << " size=" << pred->second); } if (succ == free_space.end()) { STXXL_ERRMSG("succ==free_space.end()"); } else { if (succ == free_space.begin()) STXXL_ERRMSG("succ==free_space.begin()"); STXXL_ERRMSG("succ: begin=" << succ->first << " size=" << succ->second); } dump(); } void DiskAllocator::add_free_region(stxxl::int64 block_pos, stxxl::int64 block_size) { //assert(block_size); //dump(); STXXL_VERBOSE2("Deallocating a block with size: " << block_size << " position: " << block_pos); stxxl::int64 region_pos = block_pos; stxxl::int64 region_size = block_size; if (!free_space.empty()) { sortseq::iterator succ = free_space.upper_bound(region_pos); sortseq::iterator pred = succ; if (pred != free_space.begin()) pred--; if (pred != free_space.end()) { if (pred->first <= region_pos && pred->first + pred->second > region_pos) { STXXL_THROW(bad_ext_alloc, "DiskAllocator::check_corruption", "Error: double deallocation of external memory, trying to deallocate region " << region_pos << " + " << region_size << " in empty space [" << pred->first << " + " << pred->second << "]"); } } if (succ != free_space.end()) { if (region_pos <= succ->first && region_pos + region_size > succ->first) { STXXL_THROW(bad_ext_alloc, "DiskAllocator::check_corruption", "Error: double deallocation of external memory, trying to deallocate region " << region_pos << " + " << region_size << " which overlaps empty space [" << succ->first << " + " << succ->second << "]"); } } if (succ == free_space.end()) { if (pred == free_space.end()) { deallocation_error(block_pos, block_size, pred, succ); assert(pred != free_space.end()); } if ((*pred).first + (*pred).second == region_pos) { // coalesce with predecessor region_size += (*pred).second; region_pos = (*pred).first; free_space.erase(pred); } } else { if (free_space.size() > 1) { #if 0 if (pred == succ) { deallocation_error(block_pos, block_size, pred, succ); assert(pred != succ); } #endif bool succ_is_not_the_first = (succ != free_space.begin()); if ((*succ).first == region_pos + region_size) { // coalesce with successor region_size += (*succ).second; free_space.erase(succ); } if (succ_is_not_the_first) { if (pred == free_space.end()) { deallocation_error(block_pos, block_size, pred, succ); assert(pred != free_space.end()); } if ((*pred).first + (*pred).second == region_pos) { // coalesce with predecessor region_size += (*pred).second; region_pos = (*pred).first; free_space.erase(pred); } } } else { if ((*succ).first == region_pos + region_size) { // coalesce with successor region_size += (*succ).second; free_space.erase(succ); } } } } free_space[region_pos] = region_size; free_bytes += block_size; //dump(); } __STXXL_END_NAMESPACE // vim: et:ts=4:sw=4 stxxl-1.3.1/mng/Makefile0000644000175000017500000000702611463073050014737 0ustar andreasandreasinclude Makefile.common include ../make.settings tests: $(TESTS) #tests: $(TESTS_NON_MSVC) lib: mng.$(OBJEXT) config.$(OBJEXT) diskallocator.$(OBJEXT) mng.$(OBJEXT): mng.cpp $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c mng.cpp config.$(OBJEXT): config.cpp $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c config.cpp diskallocator.$(OBJEXT): diskallocator.cpp $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c diskallocator.cpp DEPENDENCIES = $(COMMON_FILES) $(IO_LAYER_FILES) $(MNG_LAYER_FILES) test_mng: test_mng.$(EXEEXT) test_mng.$(EXEEXT): test_mng.cpp $(DEPENDENCIES) $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c test_mng.cpp -DSTXXL_VERBOSE_LEVEL=2 $(LINKER) test_mng.$(OBJEXT) $(OUT)test_mng.$(EXEEXT) $(STXXL_LINKER_OPTIONS) test_mng1: test_mng1.$(EXEEXT) test_mng1.$(EXEEXT): test_mng1.cpp $(DEPENDENCIES) $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c test_mng1.cpp -DSTXXL_VERBOSE_LEVEL=2 $(LINKER) test_mng1.$(OBJEXT) $(OUT)test_mng1.$(EXEEXT) $(STXXL_LINKER_OPTIONS) test_buf_streams: test_buf_streams.$(EXEEXT) test_buf_streams.$(EXEEXT): test_buf_streams.cpp $(DEPENDENCIES) $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c test_buf_streams.cpp $(LINKER) test_buf_streams.$(OBJEXT) $(OUT)test_buf_streams.$(EXEEXT) $(STXXL_LINKER_OPTIONS) test_block_alloc_strategy: test_block_alloc_strategy.$(EXEEXT) test_block_alloc_strategy.$(EXEEXT): test_block_alloc_strategy.cpp $(DEPENDENCIES) $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c test_block_alloc_strategy.cpp $(LINKER) test_block_alloc_strategy.$(OBJEXT) $(OUT)test_block_alloc_strategy.$(EXEEXT) $(STXXL_LINKER_OPTIONS) test_write_pool: test_write_pool.$(EXEEXT) test_write_pool.$(EXEEXT): test_write_pool.cpp $(DEPENDENCIES) $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c test_write_pool.cpp -DSTXXL_VERBOSE_LEVEL=1 $(LINKER) test_write_pool.$(OBJEXT) $(OUT)test_write_pool.$(EXEEXT) $(STXXL_LINKER_OPTIONS) test_prefetch_pool: test_prefetch_pool.$(EXEEXT) test_prefetch_pool.$(EXEEXT): test_prefetch_pool.cpp $(DEPENDENCIES) $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c test_prefetch_pool.cpp -DSTXXL_VERBOSE_LEVEL=2 $(LINKER) test_prefetch_pool.$(OBJEXT) $(OUT)test_prefetch_pool.$(EXEEXT) $(STXXL_LINKER_OPTIONS) test_mng_recursive_alloc: test_mng_recursive_alloc.$(EXEEXT) test_mng_recursive_alloc.$(EXEEXT): test_mng_recursive_alloc.cpp $(DEPENDENCIES) $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c test_mng_recursive_alloc.cpp -DSTXXL_VERBOSE_LEVEL=3 $(LINKER) test_mng_recursive_alloc.$(OBJEXT) $(OUT)test_mng_recursive_alloc.$(EXEEXT) $(STXXL_LINKER_OPTIONS) test_pool_pair: test_pool_pair.$(EXEEXT) test_pool_pair.$(EXEEXT): test_pool_pair.cpp $(DEPENDENCIES) $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c test_pool_pair.cpp $(LINKER) test_pool_pair.$(OBJEXT) $(OUT)test_pool_pair.$(EXEEXT) $(STXXL_LINKER_OPTIONS) test_read_write_pool: test_read_write_pool.$(EXEEXT) test_read_write_pool.$(EXEEXT): test_read_write_pool.cpp $(DEPENDENCIES) $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c test_read_write_pool.cpp $(LINKER) test_read_write_pool.$(OBJEXT) $(OUT)test_read_write_pool.$(EXEEXT) $(STXXL_LINKER_OPTIONS) test_aligned: test_aligned.$(EXEEXT) test_aligned.$(EXEEXT): test_aligned.cpp $(DEPENDENCIES) $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c test_aligned.cpp $(LINKER) test_aligned.$(OBJEXT) $(OUT)test_aligned.$(EXEEXT) $(STXXL_LINKER_OPTIONS) unittest: unittest.$(EXEEXT) $(DEPENDENCIES) unittest.$(EXEEXT): unittest.cpp $(COMPILER) $(STXXL_COMPILER_OPTIONS) $(CPPUNIT_COMPILER_OPTIONS) -c unittest.cpp $(LINKER) unittest.$(OBJEXT) $(OUT)unittest.$(EXEEXT) $(STXXL_LINKER_OPTIONS) $(CPPUNIT_LINKER_OPTIONS) clean: $(RM) $(CLEAN_TARGETS) stxxl-1.3.1/Doxyfile0000644000175000017500000020650511535667713014246 0ustar andreasandreas# Doxyfile 1.7.1 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project # # All text after a hash (#) is considered a comment and will be ignored # The format is: # TAG = value [value, ...] # For lists items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (" ") #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # This tag specifies the encoding used for all characters in the config file # that follow. The default is UTF-8 which is also the encoding used for all # text before the first occurrence of this tag. Doxygen uses libiconv (or the # iconv built into libc) for the transcoding. See # http://www.gnu.org/software/libiconv for the list of possible encodings. DOXYFILE_ENCODING = UTF-8 # The PROJECT_NAME tag is a single word (or a sequence of words surrounded # by quotes) that should identify the project. PROJECT_NAME = Stxxl # The PROJECT_NUMBER tag can be used to enter a project or revision number. # This could be handy for archiving the generated documentation or # if some version control system is used. PROJECT_NUMBER = 1.3.1 # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) # base path where the generated documentation will be put. # If a relative path is entered, it will be relative to the location # where doxygen was started. If left blank the current directory will be used. OUTPUT_DIRECTORY = doc/doxy/ # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create # 4096 sub-directories (in 2 levels) under the output directory of each output # format and will distribute the generated files over these directories. # Enabling this option can be useful when feeding doxygen a huge amount of # source files, where putting all generated files in the same directory would # otherwise cause performance problems for the file system. CREATE_SUBDIRS = NO # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. # The default language is English, other supported languages are: # Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, # Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, # Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English # messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, # Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrilic, Slovak, # Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. OUTPUT_LANGUAGE = English # If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will # include brief member descriptions after the members that are listed in # the file and class documentation (similar to JavaDoc). # Set to NO to disable this. BRIEF_MEMBER_DESC = YES # If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend # the brief description of a member or function before the detailed description. # Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. REPEAT_BRIEF = YES # This tag implements a quasi-intelligent brief description abbreviator # that is used to form the text in various listings. Each string # in this list, if found as the leading text of the brief description, will be # stripped from the text and the result after processing the whole list, is # used as the annotated text. Otherwise, the brief description is used as-is. # If left blank, the following values are used ("$name" is automatically # replaced with the name of the entity): "The $name class" "The $name widget" # "The $name file" "is" "provides" "specifies" "contains" # "represents" "a" "an" "the" ABBREVIATE_BRIEF = # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then # Doxygen will generate a detailed section even if there is only a brief # description. ALWAYS_DETAILED_SEC = YES # If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all # inherited members of a class in the documentation of that class as if those # members were ordinary class members. Constructors, destructors and assignment # operators of the base classes will not be shown. INLINE_INHERITED_MEMB = NO # If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full # path before files name in the file list and in the header files. If set # to NO the shortest path that makes the file name unique will be used. FULL_PATH_NAMES = NO # If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag # can be used to strip a user-defined part of the path. Stripping is # only done if one of the specified strings matches the left-hand part of # the path. The tag can be used to show relative paths in the file list. # If left blank the directory from which doxygen is run is used as the # path to strip. STRIP_FROM_PATH = # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of # the path mentioned in the documentation of a class, which tells # the reader which header file to include in order to use a class. # If left blank only the name of the header file containing the class # definition is used. Otherwise one should specify the include paths that # are normally passed to the compiler using the -I flag. STRIP_FROM_INC_PATH = # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter # (but less readable) file names. This can be useful is your file systems # doesn't support long names like on DOS, Mac, or CD-ROM. SHORT_NAMES = NO # If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen # will interpret the first line (until the first dot) of a JavaDoc-style # comment as the brief description. If set to NO, the JavaDoc # comments will behave just like regular Qt-style comments # (thus requiring an explicit @brief command for a brief description.) JAVADOC_AUTOBRIEF = NO # If the QT_AUTOBRIEF tag is set to YES then Doxygen will # interpret the first line (until the first dot) of a Qt-style # comment as the brief description. If set to NO, the comments # will behave just like regular Qt-style comments (thus requiring # an explicit \brief command for a brief description.) QT_AUTOBRIEF = NO # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen # treat a multi-line C++ special comment block (i.e. a block of //! or /// # comments) as a brief description. This used to be the default behaviour. # The new default is to treat a multi-line C++ comment block as a detailed # description. Set this tag to YES if you prefer the old behaviour instead. MULTILINE_CPP_IS_BRIEF = NO # If the INHERIT_DOCS tag is set to YES (the default) then an undocumented # member inherits the documentation from any documented member that it # re-implements. INHERIT_DOCS = YES # If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce # a new page for each member. If set to NO, the documentation of a member will # be part of the file/class/namespace that contains it. SEPARATE_MEMBER_PAGES = NO # The TAB_SIZE tag can be used to set the number of spaces in a tab. # Doxygen uses this value to replace tabs by spaces in code fragments. TAB_SIZE = 8 # This tag can be used to specify a number of aliases that acts # as commands in the documentation. An alias has the form "name=value". # For example adding "sideeffect=\par Side Effects:\n" will allow you to # put the command \sideeffect (or @sideeffect) in the documentation, which # will result in a user-defined paragraph with heading "Side Effects:". # You can put \n's in the value part of an alias to insert newlines. ALIASES = # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C # sources only. Doxygen will then generate output that is more tailored for C. # For instance, some of the names that are used will be different. The list # of all members will be omitted, etc. OPTIMIZE_OUTPUT_FOR_C = NO # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java # sources only. Doxygen will then generate output that is more tailored for # Java. For instance, namespaces will be presented as packages, qualified # scopes will look different, etc. OPTIMIZE_OUTPUT_JAVA = NO # Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran # sources only. Doxygen will then generate output that is more tailored for # Fortran. OPTIMIZE_FOR_FORTRAN = NO # Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL # sources. Doxygen will then generate output that is tailored for # VHDL. OPTIMIZE_OUTPUT_VHDL = NO # Doxygen selects the parser to use depending on the extension of the files it # parses. With this tag you can assign which parser to use for a given extension. # Doxygen has a built-in mapping, but you can override or extend it using this # tag. The format is ext=language, where ext is a file extension, and language # is one of the parsers supported by doxygen: IDL, Java, Javascript, CSharp, C, # C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, C++. For instance to make # doxygen treat .inc files as Fortran files (default is PHP), and .f files as C # (default is Fortran), use: inc=Fortran f=C. Note that for custom extensions # you also need to set FILE_PATTERNS otherwise the files are not read by doxygen. EXTENSION_MAPPING = # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want # to include (a tag file for) the STL sources as input, then you should # set this tag to YES in order to let doxygen match functions declarations and # definitions whose arguments contain STL classes (e.g. func(std::string); v.s. # func(std::string) {}). This also make the inheritance and collaboration # diagrams that involve STL classes more complete and accurate. BUILTIN_STL_SUPPORT = NO # If you use Microsoft's C++/CLI language, you should set this option to YES to # enable parsing support. CPP_CLI_SUPPORT = NO # Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. # Doxygen will parse them like normal C++ but will assume all classes use public # instead of private inheritance when no explicit protection keyword is present. SIP_SUPPORT = NO # For Microsoft's IDL there are propget and propput attributes to indicate getter # and setter methods for a property. Setting this option to YES (the default) # will make doxygen to replace the get and set methods by a property in the # documentation. This will only work if the methods are indeed getting or # setting a simple type. If this is not the case, or you want to show the # methods anyway, you should set this option to NO. IDL_PROPERTY_SUPPORT = YES # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC # tag is set to YES, then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. DISTRIBUTE_GROUP_DOC = NO # Set the SUBGROUPING tag to YES (the default) to allow class member groups of # the same type (for instance a group of public functions) to be put as a # subgroup of that type (e.g. under the Public Functions section). Set it to # NO to prevent subgrouping. Alternatively, this can be done per class using # the \nosubgrouping command. SUBGROUPING = YES # When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum # is documented as struct, union, or enum with the name of the typedef. So # typedef struct TypeS {} TypeT, will appear in the documentation as a struct # with name TypeT. When disabled the typedef will appear as a member of a file, # namespace, or class. And the struct will be named TypeS. This can typically # be useful for C code in case the coding convention dictates that all compound # types are typedef'ed and only the typedef is referenced, never the tag name. TYPEDEF_HIDES_STRUCT = NO # The SYMBOL_CACHE_SIZE determines the size of the internal cache use to # determine which symbols to keep in memory and which to flush to disk. # When the cache is full, less often used symbols will be written to disk. # For small to medium size projects (<1000 input files) the default value is # probably good enough. For larger projects a too small cache size can cause # doxygen to be busy swapping symbols to and from disk most of the time # causing a significant performance penality. # If the system has enough physical memory increasing the cache will improve the # performance by keeping more symbols in memory. Note that the value works on # a logarithmic scale so increasing the size by one will rougly double the # memory usage. The cache size is given by this formula: # 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, # corresponding to a cache size of 2^16 = 65536 symbols SYMBOL_CACHE_SIZE = 0 #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- # If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in # documentation are documented, even if no documentation was available. # Private class members and static file members will be hidden unless # the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES EXTRACT_ALL = NO # If the EXTRACT_PRIVATE tag is set to YES all private members of a class # will be included in the documentation. EXTRACT_PRIVATE = NO # If the EXTRACT_STATIC tag is set to YES all static members of a file # will be included in the documentation. EXTRACT_STATIC = NO # If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) # defined locally in source files will be included in the documentation. # If set to NO only classes defined in header files are included. EXTRACT_LOCAL_CLASSES = NO # This flag is only useful for Objective-C code. When set to YES local # methods, which are defined in the implementation section but not in # the interface are included in the documentation. # If set to NO (the default) only methods in the interface are included. EXTRACT_LOCAL_METHODS = NO # If this flag is set to YES, the members of anonymous namespaces will be # extracted and appear in the documentation as a namespace called # 'anonymous_namespace{file}', where file will be replaced with the base # name of the file that contains the anonymous namespace. By default # anonymous namespace are hidden. EXTRACT_ANON_NSPACES = NO # If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all # undocumented members of documented classes, files or namespaces. # If set to NO (the default) these members will be included in the # various overviews, but no documentation section is generated. # This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_MEMBERS = NO # If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. # If set to NO (the default) these classes will be included in the various # overviews. This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_CLASSES = YES # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all # friend (class|struct|union) declarations. # If set to NO (the default) these declarations will be included in the # documentation. HIDE_FRIEND_COMPOUNDS = YES # If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any # documentation blocks found inside the body of a function. # If set to NO (the default) these blocks will be appended to the # function's detailed documentation block. HIDE_IN_BODY_DOCS = NO # The INTERNAL_DOCS tag determines if documentation # that is typed after a \internal command is included. If the tag is set # to NO (the default) then the documentation will be excluded. # Set it to YES to include the internal documentation. INTERNAL_DOCS = YES # If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate # file names in lower-case letters. If set to YES upper-case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows # and Mac users are advised to set this option to NO. CASE_SENSE_NAMES = YES # If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen # will show members with their full class and namespace scopes in the # documentation. If set to YES the scope will be hidden. HIDE_SCOPE_NAMES = NO # If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen # will put a list of the files that are included by a file in the documentation # of that file. SHOW_INCLUDE_FILES = YES # If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen # will list include files with double quotes in the documentation # rather than with sharp brackets. FORCE_LOCAL_INCLUDES = NO # If the INLINE_INFO tag is set to YES (the default) then a tag [inline] # is inserted in the documentation for inline members. INLINE_INFO = YES # If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen # will sort the (detailed) documentation of file and class members # alphabetically by member name. If set to NO the members will appear in # declaration order. SORT_MEMBER_DOCS = YES # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the # brief documentation of file, namespace and class members alphabetically # by member name. If set to NO (the default) the members will appear in # declaration order. SORT_BRIEF_DOCS = NO # If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen # will sort the (brief and detailed) documentation of class members so that # constructors and destructors are listed first. If set to NO (the default) # the constructors will appear in the respective orders defined by # SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. # This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO # and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. SORT_MEMBERS_CTORS_1ST = NO # If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the # hierarchy of group names into alphabetical order. If set to NO (the default) # the group names will appear in their defined order. SORT_GROUP_NAMES = NO # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be # sorted by fully-qualified names, including namespaces. If set to # NO (the default), the class list will be sorted only by class name, # not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. # Note: This option applies only to the class list, not to the # alphabetical list. SORT_BY_SCOPE_NAME = NO # The GENERATE_TODOLIST tag can be used to enable (YES) or # disable (NO) the todo list. This list is created by putting \todo # commands in the documentation. GENERATE_TODOLIST = YES # The GENERATE_TESTLIST tag can be used to enable (YES) or # disable (NO) the test list. This list is created by putting \test # commands in the documentation. GENERATE_TESTLIST = YES # The GENERATE_BUGLIST tag can be used to enable (YES) or # disable (NO) the bug list. This list is created by putting \bug # commands in the documentation. GENERATE_BUGLIST = YES # The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or # disable (NO) the deprecated list. This list is created by putting # \deprecated commands in the documentation. GENERATE_DEPRECATEDLIST= YES # The ENABLED_SECTIONS tag can be used to enable conditional # documentation sections, marked by \if sectionname ... \endif. ENABLED_SECTIONS = # The MAX_INITIALIZER_LINES tag determines the maximum number of lines # the initial value of a variable or define consists of for it to appear in # the documentation. If the initializer consists of more lines than specified # here it will be hidden. Use a value of 0 to hide initializers completely. # The appearance of the initializer of individual variables and defines in the # documentation can be controlled using \showinitializer or \hideinitializer # command in the documentation regardless of this setting. MAX_INITIALIZER_LINES = 30 # Set the SHOW_USED_FILES tag to NO to disable the list of files generated # at the bottom of the documentation of classes and structs. If set to YES the # list will mention the files that were used to generate the documentation. SHOW_USED_FILES = YES # If the sources in your project are distributed over multiple directories # then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy # in the documentation. The default is NO. SHOW_DIRECTORIES = NO # Set the SHOW_FILES tag to NO to disable the generation of the Files page. # This will remove the Files entry from the Quick Index and from the # Folder Tree View (if specified). The default is YES. SHOW_FILES = YES # Set the SHOW_NAMESPACES tag to NO to disable the generation of the # Namespaces page. # This will remove the Namespaces entry from the Quick Index # and from the Folder Tree View (if specified). The default is YES. SHOW_NAMESPACES = YES # The FILE_VERSION_FILTER tag can be used to specify a program or script that # doxygen should invoke to get the current version for each file (typically from # the version control system). Doxygen will invoke the program by executing (via # popen()) the command , where is the value of # the FILE_VERSION_FILTER tag, and is the name of an input file # provided by doxygen. Whatever the program writes to standard output # is used as the file version. See the manual for examples. FILE_VERSION_FILTER = # The LAYOUT_FILE tag can be used to specify a layout file which will be parsed # by doxygen. The layout file controls the global structure of the generated # output files in an output format independent way. The create the layout file # that represents doxygen's defaults, run doxygen with the -l option. # You can optionally specify a file name after the option, if omitted # DoxygenLayout.xml will be used as the name of the layout file. LAYOUT_FILE = #--------------------------------------------------------------------------- # configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated # by doxygen. Possible values are YES and NO. If left blank NO is used. QUIET = NO # The WARNINGS tag can be used to turn on/off the warning messages that are # generated by doxygen. Possible values are YES and NO. If left blank # NO is used. WARNINGS = YES # If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings # for undocumented members. If EXTRACT_ALL is set to YES then this flag will # automatically be disabled. WARN_IF_UNDOCUMENTED = YES # If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for # potential errors in the documentation, such as not documenting some # parameters in a documented function, or documenting parameters that # don't exist or using markup commands wrongly. WARN_IF_DOC_ERROR = YES # This WARN_NO_PARAMDOC option can be abled to get warnings for # functions that are documented, but have no documentation for their parameters # or return value. If set to NO (the default) doxygen will only warn about # wrong or incomplete parameter documentation, but not about the absence of # documentation. WARN_NO_PARAMDOC = NO # The WARN_FORMAT tag determines the format of the warning messages that # doxygen can produce. The string should contain the $file, $line, and $text # tags, which will be replaced by the file and line number from which the # warning originated and the warning text. Optionally the format may contain # $version, which will be replaced by the version of the file (if it could # be obtained via FILE_VERSION_FILTER) WARN_FORMAT = "$file:$line: $text " # The WARN_LOGFILE tag can be used to specify a file to which warning # and error messages should be written. If left blank the output is written # to stderr. WARN_LOGFILE = #--------------------------------------------------------------------------- # configuration options related to the input files #--------------------------------------------------------------------------- # The INPUT tag can be used to specify the files and/or directories that contain # documented source files. You may enter file names like "myfile.cpp" or # directories like "/usr/src/myproject". Separate the files or directories # with spaces. INPUT = doxymain.h \ io/ \ common/ \ mng/ \ containers/ \ containers/btree/ \ algo/ \ stream/ \ utils/ \ include/stxxl/ \ include/stxxl/bits/algo/ \ include/stxxl/bits/common/ \ include/stxxl/bits/compat/ \ include/stxxl/bits/containers/ \ include/stxxl/bits/containers/btree/ \ include/stxxl/bits/io/ \ include/stxxl/bits/mng/ \ include/stxxl/bits/stream/ \ include/stxxl/bits/utils/ # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is # also the default input encoding. Doxygen uses libiconv (or the iconv built # into libc) for the transcoding. See http://www.gnu.org/software/libiconv for # the list of possible encodings. INPUT_ENCODING = UTF-8 # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank the following patterns are tested: # *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx # *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90 FILE_PATTERNS = *.h \ *.cpp # The RECURSIVE tag can be used to turn specify whether or not subdirectories # should be searched for input files as well. Possible values are YES and NO. # If left blank NO is used. RECURSIVE = NO # The EXCLUDE tag can be used to specify files and/or directories that should # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. EXCLUDE = # The EXCLUDE_SYMLINKS tag can be used select whether or not files or # directories that are symbolic links (a Unix filesystem feature) are excluded # from the input. EXCLUDE_SYMLINKS = NO # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude # certain files from those directories. Note that the wildcards are matched # against the file with absolute path, so to exclude all test directories # for example use the pattern */test/* EXCLUDE_PATTERNS = # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the # output. The symbol name can be a fully qualified name, a word, or if the # wildcard * is used, a substring. Examples: ANamespace, AClass, # AClass::ANamespace, ANamespace::*Test EXCLUDE_SYMBOLS = # The EXAMPLE_PATH tag can be used to specify one or more files or # directories that contain example code fragments that are included (see # the \include command). EXAMPLE_PATH = . # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank all files are included. EXAMPLE_PATTERNS = *.cpp # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude # commands irrespective of the value of the RECURSIVE tag. # Possible values are YES and NO. If left blank NO is used. EXAMPLE_RECURSIVE = YES # The IMAGE_PATH tag can be used to specify one or more files or # directories that contain image that are included in the documentation (see # the \image command). IMAGE_PATH = images/ # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program # by executing (via popen()) the command , where # is the value of the INPUT_FILTER tag, and is the name of an # input file. Doxygen will then use the output that the filter program writes # to standard output. # If FILTER_PATTERNS is specified, this tag will be # ignored. INPUT_FILTER = # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern # basis. # Doxygen will compare the file name with each pattern and apply the # filter if there is a match. # The filters are a list of the form: # pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further # info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER # is applied to all files. FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using # INPUT_FILTER) will be used to filter the input files when producing source # files to browse (i.e. when SOURCE_BROWSER is set to YES). FILTER_SOURCE_FILES = NO #--------------------------------------------------------------------------- # configuration options related to source browsing #--------------------------------------------------------------------------- # If the SOURCE_BROWSER tag is set to YES then a list of source files will # be generated. Documented entities will be cross-referenced with these sources. # Note: To get rid of all source code in the generated output, make sure also # VERBATIM_HEADERS is set to NO. SOURCE_BROWSER = NO # Setting the INLINE_SOURCES tag to YES will include the body # of functions and classes directly in the documentation. INLINE_SOURCES = NO # Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct # doxygen to hide any special comment blocks from generated source code # fragments. Normal C and C++ comments will always remain visible. STRIP_CODE_COMMENTS = YES # If the REFERENCED_BY_RELATION tag is set to YES # then for each documented function all documented # functions referencing it will be listed. REFERENCED_BY_RELATION = YES # If the REFERENCES_RELATION tag is set to YES # then for each documented function all documented entities # called/used by that function will be listed. REFERENCES_RELATION = YES # If the REFERENCES_LINK_SOURCE tag is set to YES (the default) # and SOURCE_BROWSER tag is set to YES, then the hyperlinks from # functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will # link to the source code. # Otherwise they will link to the documentation. REFERENCES_LINK_SOURCE = YES # If the USE_HTAGS tag is set to YES then the references to source code # will point to the HTML generated by the htags(1) tool instead of doxygen # built-in source browser. The htags tool is part of GNU's global source # tagging system (see http://www.gnu.org/software/global/global.html). You # will need version 4.8.6 or higher. USE_HTAGS = NO # If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen # will generate a verbatim copy of the header file for each class for # which an include is specified. Set to NO to disable this. VERBATIM_HEADERS = YES #--------------------------------------------------------------------------- # configuration options related to the alphabetical class index #--------------------------------------------------------------------------- # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index # of all compounds will be generated. Enable this if the project # contains a lot of classes, structs, unions or interfaces. ALPHABETICAL_INDEX = NO # If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then # the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns # in which this list will be split (can be a number in the range [1..20]) COLS_IN_ALPHA_INDEX = 5 # In case all classes in a project start with a common prefix, all # classes will be put under the same header in the alphabetical index. # The IGNORE_PREFIX tag can be used to specify one or more prefixes that # should be ignored while generating the index headers. IGNORE_PREFIX = #--------------------------------------------------------------------------- # configuration options related to the HTML output #--------------------------------------------------------------------------- # If the GENERATE_HTML tag is set to YES (the default) Doxygen will # generate HTML output. GENERATE_HTML = YES # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `html' will be used as the default path. HTML_OUTPUT = html # The HTML_FILE_EXTENSION tag can be used to specify the file extension for # each generated HTML page (for example: .htm,.php,.asp). If it is left blank # doxygen will generate files with .html extension. HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a personal HTML header for # each generated HTML page. If it is left blank doxygen will generate a # standard header. HTML_HEADER = # The HTML_FOOTER tag can be used to specify a personal HTML footer for # each generated HTML page. If it is left blank doxygen will generate a # standard footer. HTML_FOOTER = # If the HTML_FOOTER_DESCRIPTION tag is set to YES, Doxygen will # add generated date, project name and doxygen version to HTML footer. HTML_FOOTER_DESCRIPTION= NO # The HTML_STYLESHEET tag can be used to specify a user-defined cascading # style sheet that is used by each HTML page. It can be used to # fine-tune the look of the HTML output. If the tag is left blank doxygen # will generate a default style sheet. Note that doxygen will try to copy # the style sheet file to the HTML output directory, so don't put your own # stylesheet in the HTML output directory as well, or it will be erased! HTML_STYLESHEET = # The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. # Doxygen will adjust the colors in the stylesheet and background images # according to this color. Hue is specified as an angle on a colorwheel, # see http://en.wikipedia.org/wiki/Hue for more information. # For instance the value 0 represents red, 60 is yellow, 120 is green, # 180 is cyan, 240 is blue, 300 purple, and 360 is red again. # The allowed range is 0 to 359. HTML_COLORSTYLE_HUE = 220 # The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of # the colors in the HTML output. For a value of 0 the output will use # grayscales only. A value of 255 will produce the most vivid colors. HTML_COLORSTYLE_SAT = 100 # The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to # the luminance component of the colors in the HTML output. Values below # 100 gradually make the output lighter, whereas values above 100 make # the output darker. The value divided by 100 is the actual gamma applied, # so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2, # and 100 does not change the gamma. HTML_COLORSTYLE_GAMMA = 80 # If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML # page will contain the date and time when the page was generated. Setting # this to NO can help when comparing the output of multiple runs. HTML_TIMESTAMP = NO # If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, # files or namespaces will be aligned in HTML using tables. If set to # NO a bullet list will be used. HTML_ALIGN_MEMBERS = YES # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML # documentation will contain sections that can be hidden and shown after the # page has loaded. For this to work a browser that supports # JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox # Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). HTML_DYNAMIC_SECTIONS = NO # If the GENERATE_DOCSET tag is set to YES, additional index files # will be generated that can be used as input for Apple's Xcode 3 # integrated development environment, introduced with OSX 10.5 (Leopard). # To create a documentation set, doxygen will generate a Makefile in the # HTML output directory. Running make will produce the docset in that # directory and running "make install" will install the docset in # ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find # it at startup. # See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html # for more information. GENERATE_DOCSET = NO # When GENERATE_DOCSET tag is set to YES, this tag determines the name of the # feed. A documentation feed provides an umbrella under which multiple # documentation sets from a single provider (such as a company or product suite) # can be grouped. DOCSET_FEEDNAME = "Doxygen generated docs" # When GENERATE_DOCSET tag is set to YES, this tag specifies a string that # should uniquely identify the documentation set bundle. This should be a # reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen # will append .docset to the name. DOCSET_BUNDLE_ID = org.doxygen.Project # When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely identify # the documentation publisher. This should be a reverse domain-name style # string, e.g. com.mycompany.MyDocSet.documentation. DOCSET_PUBLISHER_ID = org.doxygen.Publisher # The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher. DOCSET_PUBLISHER_NAME = Publisher # If the GENERATE_HTMLHELP tag is set to YES, additional index files # will be generated that can be used as input for tools like the # Microsoft HTML help workshop to generate a compiled HTML help file (.chm) # of the generated HTML documentation. GENERATE_HTMLHELP = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can # be used to specify the file name of the resulting .chm file. You # can add a path in front of the file if the result should not be # written to the html output directory. CHM_FILE = # If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can # be used to specify the location (absolute path including file name) of # the HTML help compiler (hhc.exe). If non-empty doxygen will try to run # the HTML help compiler on the generated index.hhp. HHC_LOCATION = # If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag # controls if a separate .chi index file is generated (YES) or that # it should be included in the master .chm file (NO). GENERATE_CHI = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING # is used to encode HtmlHelp index (hhk), content (hhc) and project file # content. CHM_INDEX_ENCODING = # If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag # controls whether a binary table of contents is generated (YES) or a # normal table of contents (NO) in the .chm file. BINARY_TOC = NO # The TOC_EXPAND flag can be set to YES to add extra items for group members # to the contents of the HTML help documentation and to the tree view. TOC_EXPAND = NO # If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and # QHP_VIRTUAL_FOLDER are set, an additional index file will be generated # that can be used as input for Qt's qhelpgenerator to generate a # Qt Compressed Help (.qch) of the generated HTML documentation. GENERATE_QHP = NO # If the QHG_LOCATION tag is specified, the QCH_FILE tag can # be used to specify the file name of the resulting .qch file. # The path specified is relative to the HTML output folder. QCH_FILE = # The QHP_NAMESPACE tag specifies the namespace to use when generating # Qt Help Project output. For more information please see # http://doc.trolltech.com/qthelpproject.html#namespace QHP_NAMESPACE = # The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating # Qt Help Project output. For more information please see # http://doc.trolltech.com/qthelpproject.html#virtual-folders QHP_VIRTUAL_FOLDER = doc # If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to # add. For more information please see # http://doc.trolltech.com/qthelpproject.html#custom-filters QHP_CUST_FILTER_NAME = # The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the # custom filter to add. For more information please see # # Qt Help Project / Custom Filters. QHP_CUST_FILTER_ATTRS = # The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this # project's # filter section matches. # # Qt Help Project / Filter Attributes. QHP_SECT_FILTER_ATTRS = # If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can # be used to specify the location of Qt's qhelpgenerator. # If non-empty doxygen will try to run qhelpgenerator on the generated # .qhp file. QHG_LOCATION = # If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files # will be generated, which together with the HTML files, form an Eclipse help # plugin. To install this plugin and make it available under the help contents # menu in Eclipse, the contents of the directory containing the HTML and XML # files needs to be copied into the plugins directory of eclipse. The name of # the directory within the plugins directory should be the same as # the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before # the help appears. GENERATE_ECLIPSEHELP = NO # A unique identifier for the eclipse help plugin. When installing the plugin # the directory name containing the HTML and XML files should also have # this name. ECLIPSE_DOC_ID = org.doxygen.Project # The DISABLE_INDEX tag can be used to turn on/off the condensed index at # top of each HTML page. The value NO (the default) enables the index and # the value YES disables it. DISABLE_INDEX = NO # This tag can be used to set the number of enum values (range [1..20]) # that doxygen will group on one line in the generated HTML documentation. ENUM_VALUES_PER_LINE = 4 # The GENERATE_TREEVIEW tag is used to specify whether a tree-like index # structure should be generated to display hierarchical information. # If the tag value is set to YES, a side panel will be generated # containing a tree-like index structure (just like the one that # is generated for HTML Help). For this to work a browser that supports # JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). # Windows users are probably better off using the HTML help feature. GENERATE_TREEVIEW = NO # By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories, # and Class Hierarchy pages using a tree view instead of an ordered list. USE_INLINE_TREES = NO # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be # used to set the initial width (in pixels) of the frame in which the tree # is shown. TREEVIEW_WIDTH = 250 # When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open # links to external symbols imported via tag files in a separate window. EXT_LINKS_IN_WINDOW = NO # Use this tag to change the font size of Latex formulas included # as images in the HTML documentation. The default is 10. Note that # when you change the font size after a successful doxygen run you need # to manually remove any form_*.png images from the HTML output directory # to force them to be regenerated. FORMULA_FONTSIZE = 10 # Use the FORMULA_TRANPARENT tag to determine whether or not the images # generated for formulas are transparent PNGs. Transparent PNGs are # not supported properly for IE 6.0, but are supported on all modern browsers. # Note that when changing this option you need to delete any form_*.png files # in the HTML output before the changes have effect. FORMULA_TRANSPARENT = YES # When the SEARCHENGINE tag is enabled doxygen will generate a search box # for the HTML output. The underlying search engine uses javascript # and DHTML and should work on any modern browser. Note that when using # HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets # (GENERATE_DOCSET) there is already a search function so this one should # typically be disabled. For large projects the javascript based search engine # can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. SEARCHENGINE = NO # When the SERVER_BASED_SEARCH tag is enabled the search engine will be # implemented using a PHP enabled web server instead of at the web client # using Javascript. Doxygen will generate the search PHP script and index # file to put on the web server. The advantage of the server # based approach is that it scales better to large projects and allows # full text search. The disadvances is that it is more difficult to setup # and does not have live searching capabilities. SERVER_BASED_SEARCH = NO #--------------------------------------------------------------------------- # configuration options related to the LaTeX output #--------------------------------------------------------------------------- # If the GENERATE_LATEX tag is set to YES (the default) Doxygen will # generate Latex output. GENERATE_LATEX = YES # The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `latex' will be used as the default path. LATEX_OUTPUT = latex # The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be # invoked. If left blank `latex' will be used as the default command name. # Note that when enabling USE_PDFLATEX this option is only used for # generating bitmaps for formulas in the HTML output, but not in the # Makefile that is written to the output directory. LATEX_CMD_NAME = latex # The MAKEINDEX_CMD_NAME tag can be used to specify the command name to # generate index for LaTeX. If left blank `makeindex' will be used as the # default command name. MAKEINDEX_CMD_NAME = makeindex # If the COMPACT_LATEX tag is set to YES Doxygen generates more compact # LaTeX documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_LATEX = YES # The PAPER_TYPE tag can be used to set the paper type that is used # by the printer. Possible values are: a4, a4wide, letter, legal and # executive. If left blank a4wide will be used. PAPER_TYPE = a4wide # The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX # packages that should be included in the LaTeX output. EXTRA_PACKAGES = # The LATEX_HEADER tag can be used to specify a personal LaTeX header for # the generated latex document. The header should contain everything until # the first chapter. If it is left blank doxygen will generate a # standard header. Notice: only use this tag if you know what you are doing! LATEX_HEADER = # If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated # is prepared for conversion to pdf (using ps2pdf). The pdf file will # contain links (just like the HTML output) instead of page references # This makes the output suitable for online browsing using a pdf viewer. PDF_HYPERLINKS = NO # If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of # plain latex in the generated Makefile. Set this option to YES to get a # higher quality PDF documentation. USE_PDFLATEX = NO # If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. # command to the generated LaTeX files. This will instruct LaTeX to keep # running if errors occur, instead of asking the user for help. # This option is also used when generating formulas in HTML. LATEX_BATCHMODE = NO # If LATEX_HIDE_INDICES is set to YES then doxygen will not # include the index chapters (such as File Index, Compound Index, etc.) # in the output. LATEX_HIDE_INDICES = NO # If LATEX_SOURCE_CODE is set to YES then doxygen will include # source code with syntax highlighting in the LaTeX output. # Note that which sources are shown also depends on other settings # such as SOURCE_BROWSER. LATEX_SOURCE_CODE = NO #--------------------------------------------------------------------------- # configuration options related to the RTF output #--------------------------------------------------------------------------- # If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output # The RTF output is optimized for Word 97 and may not look very pretty with # other RTF readers or editors. GENERATE_RTF = NO # The RTF_OUTPUT tag is used to specify where the RTF docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `rtf' will be used as the default path. RTF_OUTPUT = rtf # If the COMPACT_RTF tag is set to YES Doxygen generates more compact # RTF documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_RTF = NO # If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated # will contain hyperlink fields. The RTF file will # contain links (just like the HTML output) instead of page references. # This makes the output suitable for online browsing using WORD or other # programs which support those fields. # Note: wordpad (write) and others do not support links. RTF_HYPERLINKS = NO # Load stylesheet definitions from file. Syntax is similar to doxygen's # config file, i.e. a series of assignments. You only have to provide # replacements, missing definitions are set to their default value. RTF_STYLESHEET_FILE = # Set optional variables used in the generation of an rtf document. # Syntax is similar to doxygen's config file. RTF_EXTENSIONS_FILE = #--------------------------------------------------------------------------- # configuration options related to the man page output #--------------------------------------------------------------------------- # If the GENERATE_MAN tag is set to YES (the default) Doxygen will # generate man pages GENERATE_MAN = NO # The MAN_OUTPUT tag is used to specify where the man pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `man' will be used as the default path. MAN_OUTPUT = man # The MAN_EXTENSION tag determines the extension that is added to # the generated man pages (default is the subroutine's section .3) MAN_EXTENSION = .3 # If the MAN_LINKS tag is set to YES and Doxygen generates man output, # then it will generate one additional man file for each entity # documented in the real man page(s). These additional files # only source the real man page, but without them the man command # would be unable to find the correct page. The default is NO. MAN_LINKS = NO #--------------------------------------------------------------------------- # configuration options related to the XML output #--------------------------------------------------------------------------- # If the GENERATE_XML tag is set to YES Doxygen will # generate an XML file that captures the structure of # the code including all documentation. GENERATE_XML = NO # The XML_OUTPUT tag is used to specify where the XML pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `xml' will be used as the default path. XML_OUTPUT = xml # The XML_SCHEMA tag can be used to specify an XML schema, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_SCHEMA = # The XML_DTD tag can be used to specify an XML DTD, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_DTD = # If the XML_PROGRAMLISTING tag is set to YES Doxygen will # dump the program listings (including syntax highlighting # and cross-referencing information) to the XML output. Note that # enabling this will significantly increase the size of the XML output. XML_PROGRAMLISTING = YES #--------------------------------------------------------------------------- # configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- # If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will # generate an AutoGen Definitions (see autogen.sf.net) file # that captures the structure of the code including all # documentation. Note that this feature is still experimental # and incomplete at the moment. GENERATE_AUTOGEN_DEF = NO #--------------------------------------------------------------------------- # configuration options related to the Perl module output #--------------------------------------------------------------------------- # If the GENERATE_PERLMOD tag is set to YES Doxygen will # generate a Perl module file that captures the structure of # the code including all documentation. Note that this # feature is still experimental and incomplete at the # moment. GENERATE_PERLMOD = NO # If the PERLMOD_LATEX tag is set to YES Doxygen will generate # the necessary Makefile rules, Perl scripts and LaTeX code to be able # to generate PDF and DVI output from the Perl module output. PERLMOD_LATEX = NO # If the PERLMOD_PRETTY tag is set to YES the Perl module output will be # nicely formatted so it can be parsed by a human reader. # This is useful # if you want to understand what is going on. # On the other hand, if this # tag is set to NO the size of the Perl module output will be much smaller # and Perl will parse it just the same. PERLMOD_PRETTY = YES # The names of the make variables in the generated doxyrules.make file # are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. # This is useful so different doxyrules.make files included by the same # Makefile don't overwrite each other's variables. PERLMOD_MAKEVAR_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the preprocessor #--------------------------------------------------------------------------- # If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will # evaluate all C-preprocessor directives found in the sources and include # files. ENABLE_PREPROCESSING = YES # If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro # names in the source code. If set to NO (the default) only conditional # compilation will be performed. Macro expansion can be done in a controlled # way by setting EXPAND_ONLY_PREDEF to YES. MACRO_EXPANSION = YES # If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES # then the macro expansion is limited to the macros specified with the # PREDEFINED and EXPAND_AS_DEFINED tags. EXPAND_ONLY_PREDEF = NO # If the SEARCH_INCLUDES tag is set to YES (the default) the includes files # in the INCLUDE_PATH (see below) will be search if a #include is found. SEARCH_INCLUDES = YES # The INCLUDE_PATH tag can be used to specify one or more directories that # contain include files that are not input files but should be processed by # the preprocessor. INCLUDE_PATH = # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard # patterns (like *.h and *.hpp) to filter out the header-files in the # directories. If left blank, the patterns specified with FILE_PATTERNS will # be used. INCLUDE_FILE_PATTERNS = # The PREDEFINED tag can be used to specify one or more macro names that # are defined before the preprocessor is started (similar to the -D option of # gcc). The argument of the tag is a list of macros of the form: name # or name=definition (no spaces). If the definition and the = are # omitted =1 is assumed. To prevent a macro definition from being # undefined via #undef or recursively expanded use the := operator # instead of the = operator. PREDEFINED = # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then # this tag can be used to specify a list of macro names that should be expanded. # The macro definition that is found in the sources will be used. # Use the PREDEFINED tag if you want to use a different macro definition. EXPAND_AS_DEFINED = # If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then # doxygen's preprocessor will remove all function-like macros that are alone # on a line, have an all uppercase name, and do not end with a semicolon. Such # function macros are typically used for boiler-plate code, and will confuse # the parser if not removed. SKIP_FUNCTION_MACROS = YES #--------------------------------------------------------------------------- # Configuration::additions related to external references #--------------------------------------------------------------------------- # The TAGFILES option can be used to specify one or more tagfiles. # Optionally an initial location of the external documentation # can be added for each tagfile. The format of a tag file without # this location is as follows: # # TAGFILES = file1 file2 ... # Adding location for the tag files is done as follows: # # TAGFILES = file1=loc1 "file2 = loc2" ... # where "loc1" and "loc2" can be relative or absolute paths or # URLs. If a location is present for each tag, the installdox tool # does not have to be run to correct the links. # Note that each tag file must have a unique name # (where the name does NOT include the path) # If a tag file is not located in the directory in which doxygen # is run, you must also specify the path to the tagfile here. TAGFILES = # When a file name is specified after GENERATE_TAGFILE, doxygen will create # a tag file that is based on the input files it reads. GENERATE_TAGFILE = # If the ALLEXTERNALS tag is set to YES all external classes will be listed # in the class index. If set to NO only the inherited external classes # will be listed. ALLEXTERNALS = NO # If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed # in the modules index. If set to NO, only the current project's groups will # be listed. EXTERNAL_GROUPS = YES # The PERL_PATH should be the absolute path and name of the perl script # interpreter (i.e. the result of `which perl'). PERL_PATH = /usr/bin/perl #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- # If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will # generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base # or super classes. Setting the tag to NO turns the diagrams off. Note that # this option is superseded by the HAVE_DOT option below. This is only a # fallback. It is recommended to install and use dot, since it yields more # powerful graphs. CLASS_DIAGRAMS = YES # You can define message sequence charts within doxygen comments using the \msc # command. Doxygen will then run the mscgen tool (see # http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the # documentation. The MSCGEN_PATH tag allows you to specify the directory where # the mscgen tool resides. If left empty the tool is assumed to be found in the # default search path. MSCGEN_PATH = # If set to YES, the inheritance and collaboration graphs will hide # inheritance and usage relations if the target is undocumented # or is not a class. HIDE_UNDOC_RELATIONS = YES # If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is # available from the path. This tool is part of Graphviz, a graph visualization # toolkit from AT&T and Lucent Bell Labs. The other options in this section # have no effect if this option is set to NO (the default) HAVE_DOT = YES # The DOT_NUM_THREADS specifies the number of dot invocations doxygen is # allowed to run in parallel. When set to 0 (the default) doxygen will # base this on the number of processors available in the system. You can set it # explicitly to a value larger than 0 to get control over the balance # between CPU load and processing speed. DOT_NUM_THREADS = 0 # By default doxygen will write a font called FreeSans.ttf to the output # directory and reference it in all dot files that doxygen generates. This # font does not include all possible unicode characters however, so when you need # these (or just want a differently looking font) you can specify the font name # using DOT_FONTNAME. You need need to make sure dot is able to find the font, # which can be done by putting it in a standard location or by setting the # DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory # containing the font. DOT_FONTNAME = FreeSans # The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. # The default size is 10pt. DOT_FONTSIZE = 10 # By default doxygen will tell dot to use the output directory to look for the # FreeSans.ttf font (which doxygen will put there itself). If you specify a # different font using DOT_FONTNAME you can set the path where dot # can find it using this tag. DOT_FONTPATH = # If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect inheritance relations. Setting this tag to YES will force the # the CLASS_DIAGRAMS tag to NO. CLASS_GRAPH = YES # If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect implementation dependencies (inheritance, containment, and # class references variables) of the class with other documented classes. COLLABORATION_GRAPH = YES # If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen # will generate a graph for groups, showing the direct groups dependencies GROUP_GRAPHS = YES # If the UML_LOOK tag is set to YES doxygen will generate inheritance and # collaboration diagrams in a style similar to the OMG's Unified Modeling # Language. UML_LOOK = NO # If set to YES, the inheritance and collaboration graphs will show the # relations between templates and their instances. TEMPLATE_RELATIONS = YES # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT # tags are set to YES then doxygen will generate a graph for each documented # file showing the direct and indirect include dependencies of the file with # other documented files. INCLUDE_GRAPH = YES # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and # HAVE_DOT tags are set to YES then doxygen will generate a graph for each # documented header file showing the documented files that directly or # indirectly include this file. INCLUDED_BY_GRAPH = YES # If the CALL_GRAPH and HAVE_DOT options are set to YES then # doxygen will generate a call dependency graph for every global function # or class method. Note that enabling this option will significantly increase # the time of a run. So in most cases it will be better to enable call graphs # for selected functions only using the \callgraph command. CALL_GRAPH = NO # If the CALLER_GRAPH and HAVE_DOT tags are set to YES then # doxygen will generate a caller dependency graph for every global function # or class method. Note that enabling this option will significantly increase # the time of a run. So in most cases it will be better to enable caller # graphs for selected functions only using the \callergraph command. CALLER_GRAPH = NO # If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen # will graphical hierarchy of all classes instead of a textual one. GRAPHICAL_HIERARCHY = YES # If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES # then doxygen will show the dependencies a directory has on other directories # in a graphical way. The dependency relations are determined by the #include # relations between the files in the directories. DIRECTORY_GRAPH = YES # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images # generated by dot. Possible values are png, jpg, or gif # If left blank png will be used. DOT_IMAGE_FORMAT = png # The tag DOT_PATH can be used to specify the path where the dot tool can be # found. If left blank, it is assumed the dot tool can be found in the path. DOT_PATH = # The DOTFILE_DIRS tag can be used to specify one or more directories that # contain dot files that are included in the documentation (see the # \dotfile command). DOTFILE_DIRS = # The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of # nodes that will be shown in the graph. If the number of nodes in a graph # becomes larger than this value, doxygen will truncate the graph, which is # visualized by representing a node as a red box. Note that doxygen if the # number of direct children of the root node in a graph is already larger than # DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note # that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. DOT_GRAPH_MAX_NODES = 50 # The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the # graphs generated by dot. A depth value of 3 means that only nodes reachable # from the root by following a path via at most 3 edges will be shown. Nodes # that lay further from the root node will be omitted. Note that setting this # option to 1 or 2 may greatly reduce the computation time needed for large # code bases. Also note that the size of a graph can be further restricted by # DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. MAX_DOT_GRAPH_DEPTH = 0 # Set the DOT_TRANSPARENT tag to YES to generate images with a transparent # background. This is disabled by default, because dot on Windows does not # seem to support this out of the box. Warning: Depending on the platform used, # enabling this option may lead to badly anti-aliased labels on the edges of # a graph (i.e. they become hard to read). DOT_TRANSPARENT = YES # Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output # files in one run (i.e. multiple -o and -T options on the command line). This # makes dot run faster, but since only newer versions of dot (>1.8.10) # support this, this feature is disabled by default. DOT_MULTI_TARGETS = NO # If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will # generate a legend page explaining the meaning of the various boxes and # arrows in the dot generated graphs. GENERATE_LEGEND = YES # If the DOT_CLEANUP tag is set to YES (the default) Doxygen will # remove the intermediate dot files that are used to generate # the various graphs. DOT_CLEANUP = YES stxxl-1.3.1/make.settings.msvc0000644000175000017500000001720211535563072016171 0ustar andreasandreas# This -*- Makefile -*- is intended for processing with nmake. ############################################################################ # make.settings.msvc # # Part of the STXXL. See http://stxxl.sourceforge.net # # Copyright (C) 2005-2008 Roman Dementiev # Copyright (C) 2006-2009 Johannes Singler # Copyright (C) 2007-2008 Andreas Beckmann # # Distributed under the Boost Software License, Version 1.0. # (See accompanying file LICENSE_1_0.txt or copy at # http://www.boost.org/LICENSE_1_0.txt) ############################################################################ # Change this file according to your paths. # change this path, do not leave spaces at the end of the line STXXL_ROOT = "$(TOPDIR)"# MAKE = nmake /NOLOGO COMPILER = cl LINKER = link WARNINGS = OPT = /O2 /Ob2 # debug is off # OPT = /Od # debug is on DEBUG_COMPILER = /MD /DNDEBUG # debug is off # DEBUG_COMPILER = /MDd /Zi # debug is on DEBUG_LINKER = /OPT:REF # debug is off # DEBUG_LINKER = /DEBUG # debug is on LIBNAME = stxxl # if you change LIBNAME, add /DSTXXL_LIBNAME=\"$(LIBNAME)\" to the compiler options include make.settings.local #### TROUBLESHOOTING # # For automatical checking of order of the output elements in # the sorters: stxxl::stream::sort, stxxl::stream::merge_runs, # stxxl::sort, and stxxl::ksort add # # /DSTXXL_CHECK_ORDER_IN_SORTS # # to the compile options. #### You usually shouldn't need to change the sections below ##### #### STXXL OPTIONS ############################################### STXXL_SPECIFIC = \ -I$(STXXL_ROOT)/include \ -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE ################################################################## #### MICROSOFT VC OPTIONS ######################################## MSVC_COMPILER_OPTIONS = /EHsc /EHs /wd4820 /wd4217 /wd4668 /wd4619 \ /wd4625 /wd4626 /wd4355 /wd4996 -D_SCL_SECURE_NO_DEPRECATE \ /F 16777216 /nologo MSVC_LINKER_OPTIONS = /LIBPATH:$(STXXL_ROOT)\lib\ lib$(LIBNAME).lib \ /LIBPATH:$(BOOST_ROOT)\lib\ /STACK:16777216 /NOLOGO ################################################################## #### BOOST OPTIONS ############################################### BOOST_COMPILER_OPTIONS = \ -D_RTLDLL \ -DBOOST_LIB_DIAGNOSTIC \ -DSTXXL_BOOST_TIMESTAMP \ -DSTXXL_BOOST_CONFIG \ -DSTXXL_BOOST_FILESYSTEM \ -DSTXXL_BOOST_THREADS \ -DSTXXL_BOOST_RANDOM \ -I$(BOOST_ROOT) ################################################################## #### DEPENDENCIES ################################################ HEADER_PATH = ../include/stxxl/bits COMMON_FILES = \ ../lib/lib$(LIBNAME).$(LIBEXT) \ $(HEADER_PATH)/namespace.h \ $(HEADER_PATH)/noncopyable.h \ $(HEADER_PATH)/version.h \ $(HEADER_PATH)/compat_hash_map.h \ $(HEADER_PATH)/compat_unique_ptr.h \ $(HEADER_PATH)/parallel.h \ $(HEADER_PATH)/singleton.h \ $(HEADER_PATH)/defines.h \ $(HEADER_PATH)/verbose.h \ $(HEADER_PATH)/unused.h \ $(HEADER_PATH)/deprecated.h \ $(HEADER_PATH)/libstxxl.h \ $(HEADER_PATH)/msvc_compatibility.h \ $(HEADER_PATH)/common/aligned_alloc.h \ $(HEADER_PATH)/common/new_alloc.h \ $(HEADER_PATH)/common/mutex.h \ $(HEADER_PATH)/common/rand.h \ $(HEADER_PATH)/common/semaphore.h \ $(HEADER_PATH)/common/state.h \ $(HEADER_PATH)/common/timer.h \ $(HEADER_PATH)/common/utils.h \ $(HEADER_PATH)/common/error_handling.h \ $(HEADER_PATH)/common/simple_vector.h \ $(HEADER_PATH)/common/switch.h \ $(HEADER_PATH)/common/tmeta.h \ $(HEADER_PATH)/common/log.h \ $(HEADER_PATH)/common/exceptions.h \ $(HEADER_PATH)/common/tuple.h \ $(HEADER_PATH)/common/types.h \ $(HEADER_PATH)/common/settings.h \ $(HEADER_PATH)/common/seed.h \ $(HEADER_PATH)/common/is_sorted.h \ $(HEADER_PATH)/common/exithandler.h \ $(HEADER_PATH)/compat/shared_ptr.h \ $(HEADER_PATH)/compat/type_traits.h IO_LAYER_FILES = \ $(HEADER_PATH)/io/io.h \ $(HEADER_PATH)/io/iostats.h \ $(HEADER_PATH)/io/completion_handler.h \ $(HEADER_PATH)/io/request_interface.h \ $(HEADER_PATH)/io/request.h \ $(HEADER_PATH)/io/request_ptr.h \ $(HEADER_PATH)/io/request_operations.h \ $(HEADER_PATH)/io/request_with_state.h \ $(HEADER_PATH)/io/request_with_waiters.h \ $(HEADER_PATH)/io/serving_request.h \ $(HEADER_PATH)/io/disk_queues.h \ $(HEADER_PATH)/io/request_queue.h \ $(HEADER_PATH)/io/request_queue_impl_worker.h \ $(HEADER_PATH)/io/request_queue_impl_qwqr.h \ $(HEADER_PATH)/io/request_queue_impl_1q.h \ $(HEADER_PATH)/io/file.h \ $(HEADER_PATH)/io/disk_queued_file.h \ $(HEADER_PATH)/io/ufs_file_base.h \ $(HEADER_PATH)/io/syscall_file.h \ $(HEADER_PATH)/io/mmap_file.h \ $(HEADER_PATH)/io/simdisk_file.h \ $(HEADER_PATH)/io/wfs_file_base.h \ $(HEADER_PATH)/io/wincall_file.h \ $(HEADER_PATH)/io/boostfd_file.h \ $(HEADER_PATH)/io/mem_file.h \ $(HEADER_PATH)/io/fileperblock_file.h \ $(HEADER_PATH)/io/wbtl_file.h \ $(HEADER_PATH)/io/create_file.h MNG_LAYER_FILES = \ $(HEADER_PATH)/mng/adaptor.h \ $(HEADER_PATH)/mng/block_alloc.h \ $(HEADER_PATH)/mng/block_alloc_interleaved.h \ $(HEADER_PATH)/mng/block_prefetcher.h \ $(HEADER_PATH)/mng/buf_istream.h \ $(HEADER_PATH)/mng/buf_ostream.h \ $(HEADER_PATH)/mng/buf_writer.h \ $(HEADER_PATH)/mng/mng.h \ $(HEADER_PATH)/mng/bid.h \ $(HEADER_PATH)/mng/typed_block.h \ $(HEADER_PATH)/mng/diskallocator.h \ $(HEADER_PATH)/mng/config.h \ $(HEADER_PATH)/mng/write_pool.h \ $(HEADER_PATH)/mng/prefetch_pool.h \ $(HEADER_PATH)/mng/read_write_pool.h CONTAINER_FILES = \ $(HEADER_PATH)/containers/pager.h \ $(HEADER_PATH)/containers/stack.h \ $(HEADER_PATH)/containers/vector.h \ $(HEADER_PATH)/containers/priority_queue.h \ $(HEADER_PATH)/containers/pq_helpers.h \ $(HEADER_PATH)/containers/pq_mergers.h \ $(HEADER_PATH)/containers/pq_ext_merger.h \ $(HEADER_PATH)/containers/pq_losertree.h \ $(HEADER_PATH)/containers/queue.h \ $(HEADER_PATH)/containers/map.h \ $(HEADER_PATH)/containers/deque.h \ $(HEADER_PATH)/containers/btree/btree.h \ $(HEADER_PATH)/containers/btree/iterator_map.h \ $(HEADER_PATH)/containers/btree/leaf.h \ $(HEADER_PATH)/containers/btree/node_cache.h \ $(HEADER_PATH)/containers/btree/root_node.h \ $(HEADER_PATH)/containers/btree/node.h \ $(HEADER_PATH)/containers/btree/iterator.h ALGO_FILES = \ $(HEADER_PATH)/algo/adaptor.h \ $(HEADER_PATH)/algo/inmemsort.h \ $(HEADER_PATH)/algo/intksort.h \ $(HEADER_PATH)/algo/run_cursor.h \ $(HEADER_PATH)/algo/sort.h \ $(HEADER_PATH)/algo/async_schedule.h \ $(HEADER_PATH)/algo/ksort.h \ $(HEADER_PATH)/algo/sort_base.h \ $(HEADER_PATH)/algo/sort_helper.h \ $(HEADER_PATH)/algo/losertree.h \ $(HEADER_PATH)/algo/scan.h \ $(HEADER_PATH)/algo/stable_ksort.h \ $(HEADER_PATH)/algo/random_shuffle.h STREAM_FILES = \ $(HEADER_PATH)/stream/stream.h \ $(HEADER_PATH)/stream/sort_stream.h \ $(HEADER_PATH)/stream/choose.h \ $(HEADER_PATH)/stream/unique.h \ $(HEADER_PATH)/stream/sorted_runs.h ################################################################### #### MISC ######################################################### OBJEXT = obj # extension of object file LIBOBJEXT = obj # extension of object files for the library LIBEXT = lib # static library file extension EXEEXT = exe # executable file extension RM = del # remove file command LIBGEN = lib /nologo /out:# library generation OUT = /out:# output file for linking and compilation CLEAN_TARGETS = *.$(OBJEXT) *.$(EXEEXT) *.$(LIBEXT) *.exe.manifest *.pdb *.exp ################################################################### STXXL_COMPILER_OPTIONS = \ $(STXXL_SPECIFIC) \ $(OPT) $(DEBUG_COMPILER) $(WARNINGS) \ $(BOOST_COMPILER_OPTIONS) \ $(MSVC_COMPILER_OPTIONS) STXXL_LINKER_OPTIONS = \ $(MSVC_LINKER_OPTIONS) \ $(DEBUG_LINKER) # vim: syn=make stxxl-1.3.1/stxxl.vcproj0000644000175000017500000003574011504165114015130 0ustar andreasandreas stxxl-1.3.1/CHANGELOG0000644000175000017500000004001111536252110013714 0ustar andreasandreasVersion 1.3.1 (10 March 2011) * Possibly breaking changes - No longer open syscall files with O_SYNC|O_DSYNC|O_RSYNC by default when doing direct I/O, to avoid a write performance decrease starting with Linux kernel version 2.6.32. A stxxl::file::SYNC flag has been added to allow forcing the O_*SYNC flags when opening files. - Lock files by default (if implemented for this file type), can by disabled via stxxl::file::NO_LOCK. - block_prefetcher now takes a completion_handler instead of a raw function pointer. Furthermore, the completion_handler is already executed after the read operation completes, not only when the issuer waits for it to complete. The I/O thread issues the call to the completion_handler, so for multiple disks, this may happen concurrently. * Internal changes, not user-visible - Change handling of (empty) filler elements in typed_block to fix mismatching struct size in nested blocks. - Removed debugmon which was very limited and disabled for a long time. * Bugfixes - Allow prefetch schedule computation of vectors that are bound to a file. - Fix race growing files during concurrent block allocation. - Allow reading a block that spans over end-of-file, fill remainder with zeroes. - Crash at program termination when using global stxxl containers. - Enable syscall_file to read/write >=2GiB of data in a single I/O operation. * New public headers: stxxl/stats, stxxl/request * Parallel mode can be switched on for internal STXXL computation selectively (i.e. without enabling it for the non-stxxl part of an application), by setting USE_PARALLEL_MODE=yes in make.settings.local. * Platform Support - add ICPC 12.0, works with both MCSTL (needs libstdc++ from GCC 4.2) and parallel mode (needs libstdc++ from GCC 4.3 (not 4.4/4.5)) - add CLANG++ 2.8 - add MSVC 2010/Windows 7 - allow the library name generated by MSVC to be changed by setting LIBNAME and redefining STXXL_LIBNAME (defaults to "stxxl") * Under-the-hood improvements - code cleanup - I/O-layer: renaming and reorganization of the request implementation * Documentation updates * Several new test programs * Several test programs improved ------------------------------------------ Version 1.3.0 (12 August 2010) * New file types - fileperblock_syscall/fileperblock_mmap/fileperblock_boostfd/fileperblock_wincall: Use a separate file for each block, which is accessed by means of the underlying file type. The "filename" given is used as a prefix of the block file names. The advantage of these file types is that unused disk space is freed earlier on the file system level. - wbtl_file: Do library-based write-combining (good for writing small blocks onto SSDs) * I/O subsystem - separate the disk number of a file (which queue to put requests in) from the fact that blocks for this file are allocated via the block manager (disk number -1 otherwise). - separate wait time counting for read and write I/Os - wait times can be logged to a separate log file (compile with -DSTXXL_WAIT_LOG_ENABLED and set STXXLWAITLOGFILE in the environment) * Parallel PQ - priority_queue now supports parallelized operations utilizing the libstdc++ parallel mode * Other new functionality - file requests can now be canceled (success not guaranteed), completion handlers are called anyway. - log file locations are now configurable by the environment variables STXXLLOGFILE and STXXLERRLOGFILE - single queue I/O scheduling - reverse_iterator added to containers types vector, deque and map - autogrow files (specified in .stxxl by a size of 0), will be deleted on normal program termination - add infrastructure to build multiple binaries with different CXXFLAGS from a single source - overwriting deleted memfile regions with uninitialized data is now optional (STXXL_CLEAR_FREE_MEMFILE_MEM) - read_write_pool that combines prefetch_pool with write_pool and ensures cache coherency - add a replaceable exit handler implementation, can be overwritten e.g. for library inclusion * Many, many bug fixes, in particular concerning - priority queue - optimal prefetch schedule - possible race condition while creating singleton instances - random_shuffle() * Platform Support - add GCC 4.4 (parallel mode features not working in GCC 4.3 can now be used) - add GCC 4.5 - initial support for GCC 4.6 - add ICPC 11.x - add Boost 1.42 - add FreeBSD - drop Solaris * New benchmarks - io/benchmark_disks: more command line paramaters for finer testing granularity - measure hard-disk and flash-disk combined performance and determine best block size pairs (io/benchmark_disk_and_flash) - benchmark using regular STXXL configuration (benchmark_configured_disks) * Possibly breaking changes - API name changes vector::touch -> vector::block_externally_updated - Template parameter changes stream::sorted_runs, trigger_entry, trigger_entry_cmp, trigger_entry_iterator - Priority of write changes - Other name changes (considered internal) typed_block<>::has_filler -> !typed_block<>::has_only_data file::delete_region -> file::discard vector::alloc_strategy -> vector::alloc_strategy_type - stxxl::sort(..., M) and stxxl::stream::sort(..., M) now adhere to to the memory limit M more strictly and throw errors instead of overallocating - Execute completion handler before notifying waiters, so far after. * Deprecated methods: - stxxl::stats::reset(), stxxl::stats::_reset_io_wait_time(): use stxxl::stats_data instead to store snapshots of the counters and compute differences * Under-the-hood improvements - I/O layer cleanup - aligned_alloc * Doxy now also lists undocumented members * stop requiring STXXL_ROOT to be a hard coded absolute path set in make.settings.local, a default of CURDIR works fine * document #defines in defines.h - switch on/off file types with STXXL_HAVE_xxx_FILE (to avoid platform compatibility problems) ------------------------------------------ Version 1.2.1 (14 August 2008) * add support for the libstdc++ parallel_mode (successor of MCSTL), new make targets: library_g++_pmode, tests_g++_pmode, clean_g++_pmode (requires g++ 4.3.2 or later) * new stxxl file type stxxl::mem_file (for debugging purposes only), helps debugging with valgrind because no memory cell ever leaves valgrind's control * properly destroy the singleton objects (block manager, disk queue threads, logger, stats, config, ...) at program exit * fixed a bug (recursive locking) in recursive block allocation * added a test program for recursive block allocation * sensible dependencies for nmake (MSVC): only rebuild files as necessary * improve performance of createdisks * human-readable output for I/O stats * replace hard coded min/max values by std::numeric_limits<>::min/max in examples * fix a case where only half of the available memory was used during recursive merging * verify stxxl::set_seed() functionality in tests * remove stxxl disk files created from default configuration (no .stxxl file found) and other temporary files at program end * stop using deprecated functions, switch to the replacements instead * unify the mutex lock handling by introducing stxxl::scoped_mutex_lock * unify the I/O wait time counting to work like read/write time counting * simplify I/O time counting with scoped_{read,write,wait}_timer * add some more tests * more code cleanup + reformatting * move some more code to the library * reduce some include dependencies * build system tuning * propagate region deletion (when blocks are freed) to the file level * fix problem in sorters where blocks were released too early * specialize is_sorted() to use const_vector_iterators, no extra writes * add c++0x style const_iterator cbegin()/cend() to all containers ------------------------------------------ Version 1.2.0 (05 July 2008) * made the block management layer thread-safe * made all size_types unsigned * stxxl::priority_queue - fixed a rare assertion - fixed a race condition by using proper block hinting - insert_queue: replaced std::priority_queue with a special implementation internal_priority_queue that allows for fast exporting of all elements - even more bugs and inefficiencies fixed - significant speed improvements * random number generators are now all seedable, should allow redoing identical program runs for debugging purposes * stxxl::noncopyable, inspired by boost::noncopyable: inheriting from this class forbids copying of objects when this is undesirable - used in all classes that had implemented their own variants previously * stxxl::vector, all sorting functions: replaced TwoToOneDimArrayRowAdaptor with ArrayOfSequencesIterator which is much faster, especially if blocks have padding * if required, verify that the sentinels satisfy a strict weak ordering * stxxl::vector: several operations sped up, several more implemented * fix existing allocation strategies and add experimental support for distinguishing between regular disks and flash devices * stxxl::stable_ksort - add experimental warning, some parts are not yet implemented - fixed an off-by-one error in memory allocation vs. usage * btree: fuse last two nodes/leaves if possible, rebalancing can fail * btree tests: ensure uniqueness of test data if required * reduce function call overhead of stxxl::debugmon if it's not activated * add public interface headers: stxxl/types, stxxl/aligned_alloc * add compatibility wrappers for standard extensions hash_map, hash_set, auto_ptr * MCSTL is only supported with g++ 4.2 and icpc 10.x * lots of small bugfixes * made the TPIE, BDB and LEDA_SM tests compile again * general code cleanup - fixed most compiler warnings - elimination of duplicate and unused code - cleaned up and sanitized debugging macros - no more 'using namespace std' and 'using namespace stxxl' - fixed ambiguities noted by g++ 4.3 - unify the #include directives - add/unify/cleanup copyright headers * general code reformatting (uncrustify) * add support for new compiler releases * portability fixes for different platforms * implemented file truncation on windows platforms * build system - lots of small modifications - now only requires GNU make 3.78 or later - check whether STXXL_ROOT has been set correctly and if unset, try autoconfiguration by creating make.settings.local with defaults - improved and simplified boost support for posix systems - Mac OS X support * changed all tests so that they behave well in their default parameters, system assumptions and return values and can be run from a script - use aligned_alloc/aligned_dealloc appropriately * added some more test programs * add misc/run_all_tests that runs all tests with sensible parameters, optionally via valgrind * checked all tests with valgrind - fixed use of uninitialized memory when writing to normal files - (optionally) initialize typed_blocks and payload data in test structs to suppress (most) uninitialized write errors when writing to disk files - fix mismatched new/delete in mcstl * update install and usage instructions * spell checked sources and documentation ------------------------------------------ Version 1.1.0 (31 July 2007) * stxxl is now hosted on SourceForge: http://stxxl.sourceforge.net/ * Restructured the source layout: - includes moves to include/ - introduced some public headers: stxxl.h, stxxl/algorithm, stxxl/bits, stxxl/deque, stxxl/io, stxxl/ksort, stxxl/mallocstats, stxxl/map, stxxl/mng, stxxl/priority_queue, stxxl/queue, stxxl/random, stxxl/scan, stxxl/sort, stxxl/stable_ksort, stxxl/stack, stxxl/stream, stxxl/timer, stxxl/vector - the header "stxxl" is no longer available, please use "stxxl.h" instead - the use of any other (internal) header is discouraged, additional public headers can be added as the need arises * Overhauled the build system: - merged configuration files, simplified option tuning - support object files and binaries with and without mcstl support existing in parallel - the library build creates stxxl.mk which can be included in an applications Makefile to set the correct compiler/linker switches for stxxl - similarly mcstxxl.mk is created for a stxxl compiled with mcstl support - add dependency tracking and improve parallelism during build * compiler support matrix: (for an up-to-date list, please see the doxygen documentation) compiler | stxxl stxxl + mcstl --------------+------------------------ GCC 4.3 | x x GCC 4.2 | x x GCC 4.1 | x n/a GCC 4.0 | x n/a GCC 3.4 | x n/a GCC 3.3 | o n/a GCC 2.95 | - n/a ICPC 9.1.051 | x x¹ ICPC 10.0.025 | x x¹ MSVC 2005 8.0 | x n/a x = full support o = partial support - = unsupported n/a = compiler does not support OpenMP which is needed by MCSTL ¹ = does not work with STL GCC 4.2.0 (ICPC bug), workaround: the first include in the program must be "stxxl/bits/common/intel_compatibility.h" * pipelined stream::sort, stream::runs_creator and stream::runs_merger are parallelized using MCSTL * obsolete files removed * fixed include dependencies * fixed lots of warnings * fixed lots of small bugs * add header compilation tests * stxxl::vector: implemented some more functions * const char* stxxl::get_version_string(): new function * comparators inherit from std::binary_function<> * cleanup, reformat the code to a consistent format (Thanks, uncrustify!) ------------------------------------------ Version 1.0e (4 June 2007) * Bugfix: for objects with the destructors, memory block were allocated in a non-aligned fashion * Internal CPU efficiency of Stxxl priority queue is improved (loser trees in external mergers are integrated) * Fixed bug with conversion of const/non-const iterators, implemented comparison and difference operations on const/non-const iterators (for vector, map, and deque) * Added operator[] to vector and deque iterators * stxxl::random_shuffle added * improved Makefile structure (thanx to Andreas Beckmann) * Allow parallel build for g++ ------------------------------------------ Version 1.0d (16 January 2007) * Support of Visual Studio 2005 Express (VC++ 8.0) * Algorithms and data structures of Stxxl can now use more than 4GB of main memory on 64-bit processors/compilers * Support of error reporting using the C++ exception mechanism ------------------------------------------- Version 1.0c (21 September 2006) * An implementation of an I/O-efficient deque * STXXL uses MCSTL library (optional) to improve the performance of stxxl::sort and pipelined sort on SMP and multicore processors. ------------------------------------------- Version 0.99 (22 March 2006) * Better compiler support: g++ (versions 3.3.x-4.0.x) and Microsoft Visual C++ 7.1 (.NET) * New B+Tree-based implementation of map (compatible with all listed above compilers): I/O-efficient map ------------------------------------------ Version 0.9 (9 August 2005) * STXXL has been ported to Windows. It now can be run under Windows XP and Windows 2000 * STXXL can be compiled now by g++ (versions 3.0.x-3.4.x, 4.0.x) and Microsoft Visual C++ 7.1 (.NET) * New data structure: I/O efficient FIFO queue ------------------------------------------ Version 0.77 (24 March 2005) * An implementation of queue is available ------------------------------------------ Version 0.75 (23 March 2005) * An implementation of map based on B+tree is available ------------------------------------------ Version 0.7 (25 January 2005) * The implementation of pipelining is extended and improved ------------------------------------------ Version 0.6 (5 September 2004) * Tested implementation of the stream package (aka pipelining) is available ------------------------------------------ Version 0.5 (21 November 2003) * The first implementation of the stream package (aka pipelining) is available * Priority queue is available ------------------------------------------ Version 0.2 (Summer 2003) * The first public release * Vectors, stacks, sorting, scanning are available stxxl-1.3.1/local/0000755000175000017500000000000011536252420013604 5ustar andreasandreasstxxl-1.3.1/local/GNUmakefile0000644000175000017500000000034511422034361015654 0ustar andreasandreasTOPDIR ?= .. CPPS := $(wildcard *.cpp) TESTS = $(CPPS:.cpp=) -include $(TOPDIR)/make.settings.local include $(TOPDIR)/Makefile.subdir.gnu -include GNUmakefile.local clean:: $(RM) $(TESTS:=.*.d) $(TESTS:=.*.o) $(TESTS:=.*.bin) stxxl-1.3.1/stream/0000755000175000017500000000000011536252420014005 5ustar andreasandreasstxxl-1.3.1/stream/test_naive_transpose.cpp0000644000175000017500000001266511535663467021002 0ustar andreasandreas/*************************************************************************** * stream/test_naive_transpose.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2010 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ //! \example stream/test_naive_transpose.cpp //! This is an example of how to use some basic algorithms from the //! stream package. The example transposes a 2D-matrix which is serialized //! as an 1D-vector. //! //! This transpose implementation is trivial, not neccessarily fast or //! efficient. There are more sophisticated and faster algorithms for external //! memory matrix transpostion than sorting, see e.g. J.S. Vitter: Algorithms //! and Data Structures for External Memory, Chapter 7.2. #include #include #include #include class streamop_matrix_transpose { unsigned cut, repeat; unsigned pos; public: typedef unsigned value_type; streamop_matrix_transpose(unsigned cut, unsigned repeat) : cut(cut), repeat(repeat), pos(0) { } value_type operator * () const { return (pos % cut) * repeat + pos / cut; } streamop_matrix_transpose & operator ++ () { ++pos; return *this; } bool empty() const { return pos == (cut * repeat); } }; template struct cmp_tuple_first : std::binary_function { typedef T value_type; typedef typename value_type::first_type first_value_type; bool operator () (const value_type & a, const value_type & b) const { return a.first < b.first; } value_type min_value() const { return value_type((std::numeric_limits::min)(), 0); } value_type max_value() const { return value_type((std::numeric_limits::max)(), 0); } }; template void dump_upper_left(const Vector & v, unsigned rows, unsigned cols, unsigned nx, unsigned ny) { int w = 5; // assumes row-major layout in the vector serialization of the matrix for (unsigned y = 0; y < ny && y < rows; ++y) { std::cout << std::setw(w) << y << ":"; for (unsigned x = 0; x < nx && x < cols; ++x) std::cout << " " << std::setw(w) << v[y * cols + x]; if (nx < cols) std::cout << " ..."; std::cout << std::endl; } if (ny < rows) std::cout << std::setw(w) << "..." << std::endl; std::cout << std::endl; } int main() { unsigned num_cols = 10000; unsigned num_rows = 5000; // buffers for streamify and materialize, // block size matches the block size of the input/output vector unsigned numbuffers = 2 * stxxl::config::get_instance()->disks_number(); // RAM to be used for sorting (in bytes) size_t memory_for_sorting = 1 << 28; /////////////////////////////////////////////////////////////////////// typedef stxxl::VECTOR_GENERATOR::result array_type; array_type input(num_rows * num_cols); array_type output(num_cols * num_rows); // fill the input array with some values for (unsigned i = 0; i < num_rows * num_cols; ++i) input[i] = i; std::cout << "Before transpose:" << std::endl; dump_upper_left(input, num_rows, num_cols, 10, 10); stxxl::stats_data stats_before(*stxxl::stats::get_instance()); // HERE streaming part begins (streamifying) // create input stream #ifdef BOOST_MSVC typedef stxxl::stream::streamify_traits::stream_type input_stream_type; #else typedef __typeof__(stxxl::stream::streamify(input.begin(), input.end())) input_stream_type; #endif input_stream_type input_stream = stxxl::stream::streamify(input.begin(), input.end(), numbuffers); // create stream of destination indices typedef streamop_matrix_transpose destination_index_stream_type; destination_index_stream_type destination_index_stream(num_cols, num_rows); // create tuple stream: (key, value) typedef stxxl::stream::make_tuple tuple_stream_type; tuple_stream_type tuple_stream(destination_index_stream, input_stream); // sort tuples by first entry (key) typedef cmp_tuple_first cmp_type; typedef stxxl::stream::sort sorted_tuple_stream_type; sorted_tuple_stream_type sorted_tuple_stream(tuple_stream, cmp_type(), memory_for_sorting); // discard the key we used for sorting, keep second entry of the tuple only (value) typedef stxxl::stream::choose sorted_element_stream_type; sorted_element_stream_type sorted_element_stream(sorted_tuple_stream); // HERE streaming part ends (materializing) array_type::iterator o = stxxl::stream::materialize(sorted_element_stream, output.begin(), output.end(), numbuffers); assert(o == output.end()); assert(sorted_element_stream.empty()); stxxl::stats_data stats_after(*stxxl::stats::get_instance()); std::cout << "After transpose:" << std::endl; dump_upper_left(output, num_cols, num_rows, 10, 10); std::cout << "I/O stats (streaming part only!)" << std::endl << (stats_after - stats_before); return 0; } // vim: et:ts=4:sw=4 stxxl-1.3.1/stream/Makefile.common0000644000175000017500000000022511535663467016753 0ustar andreasandreasTESTS = test_stream test_stream1 test_sorted_runs test_push_sort test_materialize test_naive_transpose test_loop TESTS_NON_MSVC = LIB_SRC = stxxl-1.3.1/stream/test_materialize.cpp0000644000175000017500000000533211516040032020051 0ustar andreasandreas/*************************************************************************** * stream/test_materialize.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2009 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #include #include #include struct forty_two { unsigned counter; forty_two() : counter(0) { } bool empty() const { return !(counter < 42); } int operator * () { assert(!empty()); return 42; } forty_two & operator ++ () { assert(!empty()); ++counter; return *this; } forty_two & reset() { counter = 0; return *this; } }; /* template OutputIterator_ materialize(StreamAlgorithm_ & in, OutputIterator_ out); template OutputIterator_ materialize(StreamAlgorithm_ & in, OutputIterator_ outbegin, OutputIterator_ outend); template stxxl::vector_iterator materialize(StreamAlgorithm_ & in, stxxl::vector_iterator outbegin, stxxl::vector_iterator outend, unsigned_type nbuffers = 0); template stxxl::vector_iterator materialize(StreamAlgorithm_ & in, stxxl::vector_iterator out, unsigned_type nbuffers = 0); */ int main() { stxxl::config::get_instance(); forty_two _42; std::vector v(1000); stxxl::stream::materialize(_42.reset(), v.begin()); stxxl::stream::materialize(_42.reset(), v.begin(), v.end()); stxxl::VECTOR_GENERATOR::result xv(1000); stxxl::stream::materialize(_42.reset(), xv.begin()); stxxl::stream::materialize(_42.reset(), xv.begin(), 42); stxxl::stream::materialize(_42.reset(), xv.begin(), xv.end()); stxxl::stream::materialize(_42.reset(), xv.begin(), xv.end(), 42); } stxxl-1.3.1/stream/test_push_sort.cpp0000644000175000017500000000564711535151017017611 0ustar andreasandreas/*************************************************************************** * stream/test_push_sort.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2004 Roman Dementiev * Copyright (C) 2009, 2010 Johannes Singler * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ //! \example stream/test_push_sort.cpp //! This is an example of how to use some basic algorithms from //! stream package. This example shows how to create //! \c sorted_runs data structure //! using \c stream::use_push specialization of \c stream::runs_creator class #include #include const unsigned long long megabyte = 1024 * 1024; const unsigned int block_size = 1 * megabyte; typedef unsigned value_type; struct Cmp : public std::binary_function { typedef unsigned value_type; bool operator () (const value_type & a, const value_type & b) const { return a < b; } value_type min_value() { return (std::numeric_limits::min)(); } value_type max_value() { return (std::numeric_limits::max)(); } }; int main() { #if STXXL_PARALLEL_MULTIWAY_MERGE STXXL_MSG("STXXL_PARALLEL_MULTIWAY_MERGE"); #endif // special parameter type typedef stxxl::stream::use_push InputType; typedef stxxl::stream::runs_creator CreateRunsAlg; typedef CreateRunsAlg::sorted_runs_type SortedRunsType; unsigned input_size = (50 * megabyte / sizeof(value_type)); Cmp c; CreateRunsAlg SortedRuns(c, 10 * megabyte); value_type checksum_before(0); stxxl::random_number32 rnd; for (unsigned cnt = input_size; cnt > 0; --cnt) { const value_type element = rnd(); checksum_before += element; SortedRuns.push(element); // push into the sorter } SortedRunsType Runs = SortedRuns.result(); // get sorted_runs data structure assert(stxxl::stream::check_sorted_runs(Runs, Cmp())); // merge the runs stxxl::stream::runs_merger merger(Runs, Cmp(), 10 * megabyte); stxxl::vector, block_size, STXXL_DEFAULT_ALLOC_STRATEGY> array; STXXL_MSG(input_size << " " << Runs.elements); STXXL_MSG("checksum before: " << checksum_before); value_type checksum_after(0); for (unsigned i = 0; i < input_size; ++i) { checksum_after += *merger; array.push_back(*merger); ++merger; } STXXL_MSG("checksum after: " << checksum_after); assert(stxxl::is_sorted(array.begin(), array.end(), Cmp())); assert(checksum_before == checksum_after); assert(merger.empty()); return 0; } stxxl-1.3.1/stream/GNUmakefile0000644000175000017500000000352311535663467016102 0ustar andreasandreasTOPDIR ?= .. include Makefile.common TESTS-yes += $(TESTS_NON_MSVC) include $(TOPDIR)/Makefile.subdir.gnu test_stream1.$o: CPPFLAGS += -DSTXXL_VERBOSE_LEVEL=1 test_push_sort.$o: CPPFLAGS += -DSTXXL_VERBOSE_LEVEL=0 test_stream.$o: CPPFLAGS += -DSTXXL_VERBOSE_LEVEL=1 test_materialize.$o: CPPFLAGS += -DSTXXL_VERBOSE_LEVEL=0 -DSTXXL_VERBOSE_MATERIALIZE=STXXL_VERBOSE0 ifeq ($(strip $(USE_PMODE)),yes) # ICPC 12.0: internal error: backend signals (issue 613286) $(call reduce_optimization,3,0,test_stream,Version_12.0,any,any) $(call reduce_optimization,3,0,test_stream1,Version_12.0,any,any) $(call reduce_optimization,3,0,test_sorted_runs,Version_12.0,any,any) $(call reduce_optimization,3,0,test_push_sort,Version_12.0,any,any) $(call reduce_optimization,3,0,test_naive_transpose,Version_12.0,any,any) $(call reduce_optimization,3,0,test_loop,Version_12.0,any,any) endif ifeq ($(strip $(USE_MCSTL)),yes) # ICPC 12.0: internal error: backend signals (issue 613286) $(call reduce_optimization,3,0,test_stream,Version_12.0,any,any) $(call reduce_optimization,3,0,test_stream1,Version_12.0,any,any) $(call reduce_optimization,3,0,test_sorted_runs,Version_12.0,any,any) $(call reduce_optimization,3,0,test_push_sort,Version_12.0,any,any) $(call reduce_optimization,3,0,test_naive_transpose,Version_12.0,any,any) $(call reduce_optimization,3,0,test_loop,Version_12.0,any,any) # ICPC 10.0: internal error: backend signals (issue 466173) $(call reduce_optimization,3,1,test_stream,Version_10.0,32-bit,any) $(call reduce_optimization,3,1,test_stream1,Version_10.0,32-bit,any) $(call reduce_optimization,3,0,test_sorted_runs,Version_10.0,32-bit,any) $(call reduce_optimization,3,0,test_push_sort,Version_10.0,32-bit,any) $(call reduce_optimization,3,1,test_naive_transpose,Version_10.0,32-bit,any) $(call reduce_optimization,3,1,test_loop,Version_10.0,32-bit,any) endif stxxl-1.3.1/stream/test_sorted_runs.cpp0000644000175000017500000000703111535654452020132 0ustar andreasandreas/*************************************************************************** * stream/test_sorted_runs.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2003 Roman Dementiev * Copyright (C) 2009, 2010 Johannes Singler * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ //! \example stream/test_sorted_runs.cpp //! This is an example of how to use some basic algorithms from //! stream package. This example shows how to create //! \c sorted_runs data structure from sorted sequences //! using \c stream::from_sorted_sequences specialization of \c stream::runs_creator class #include #include const unsigned long long megabyte = 1024 * 1024; const int block_size = 1 * megabyte; typedef unsigned value_type; struct Cmp : public std::binary_function { typedef unsigned value_type; bool operator () (const value_type & a, const value_type & b) const { return a < b; } value_type min_value() { return (std::numeric_limits::min)(); } value_type max_value() { return (std::numeric_limits::max)(); } }; int main() { #if STXXL_PARALLEL_MULTIWAY_MERGE STXXL_MSG("STXXL_PARALLEL_MULTIWAY_MERGE"); #endif // special parameter type typedef stxxl::stream::from_sorted_sequences InputType; typedef stxxl::stream::runs_creator CreateRunsAlg; typedef CreateRunsAlg::sorted_runs_type SortedRunsType; unsigned input_size = (50 * megabyte / sizeof(value_type)); Cmp c; CreateRunsAlg SortedRuns(c, 10 * megabyte); value_type checksum_before(0); stxxl::random_number32 rnd; stxxl::random_number<> rnd_max; for (unsigned cnt = input_size; cnt > 0; ) { unsigned run_size = rnd_max(cnt) + 1; // random run length cnt -= run_size; STXXL_MSG("current run size: " << run_size); std::vector tmp(run_size); // create temp storage for current run // fill with random numbers std::generate(tmp.begin(), tmp.end(), rnd _STXXL_FORCE_SEQUENTIAL); std::sort(tmp.begin(), tmp.end(), c); // sort for (unsigned j = 0; j < run_size; ++j) { checksum_before += tmp[j]; SortedRuns.push(tmp[j]); // push sorted values to the current run } SortedRuns.finish(); // finish current run } SortedRunsType Runs = SortedRuns.result(); // get sorted_runs data structure assert(check_sorted_runs(Runs, Cmp())); // merge the runs stxxl::stream::runs_merger merger(Runs, Cmp(), 10 * megabyte); stxxl::vector, block_size, STXXL_DEFAULT_ALLOC_STRATEGY> array; STXXL_MSG(input_size << " " << Runs.elements); STXXL_MSG("checksum before: " << checksum_before); value_type checksum_after(0); for (unsigned i = 0; i < input_size; ++i) { checksum_after += *merger; array.push_back(*merger); ++merger; } STXXL_MSG("checksum after: " << checksum_after); assert(stxxl::is_sorted(array.begin(), array.end(), Cmp())); assert(checksum_before == checksum_after); assert(merger.empty()); return 0; } stxxl-1.3.1/stream/test_loop.cpp0000644000175000017500000001563711516061102016526 0ustar andreasandreas/*************************************************************************** * stream/test_loop.cpp * * example for building a loop of stream operations * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright © 2011 Jaroslaw Fedorowicz * Copyright © 2011 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ //! \example stream/test_loop.cpp //! This is an example of how to use some basic algorithms from the //! stream package to form a loop iterating over the data. //! Some input is generated, sorted, some elements are filtered out. //! The remaining elements are transformed, sorted and processed in the //! next pass. The loop will terminate if at most one element remains. //! A split sorter is used to cut the data flow (and type dependency) cycle. #include #include #include #include #include using std::cout; using std::endl; const stxxl::uint64 memory_to_use = 3ul * 1024 * 1024 * 1024; bool verbose; struct random_generator { typedef stxxl::random_number32::value_type value_type; typedef stxxl::uint64 size_type; value_type current; size_type count; stxxl::random_number32 rnd; random_generator(size_type _count) : count(_count) { if (verbose) cout << "Random Stream: "; current = rnd(); } value_type operator * () const { return current; } random_generator & operator ++ () { count--; if (verbose) { cout << current << ", "; if (empty()) cout << endl; } current = rnd(); return *this; } bool empty() const { return (count == 0); } }; template struct Cmp : std::binary_function { bool operator () (const value_type & a, const value_type & b) const { return a < b; } static value_type min_value() { return value_type((std::numeric_limits::min)()); } static value_type max_value() { return value_type((std::numeric_limits::max)()); } }; template struct filter { typedef typename Input::value_type value_type; typedef stxxl::uint64 size_type; Input & input; value_type filter_value; size_type & counter; void apply_filter() { while (!input.empty() && *input == filter_value) { ++input; counter++; } } filter(Input & _input, value_type _filter_value, size_type & _counter) : input(_input), filter_value(_filter_value), counter(_counter) { apply_filter(); } const value_type operator * () const { return *input; } filter & operator ++ () { ++input; apply_filter(); return *this; } bool empty() const { return input.empty(); } }; template struct output { typedef typename Input::value_type value_type; Input & input; output(Input & _input) : input(_input) { } const value_type operator * () const { return *input; } output & operator ++ () { if (verbose) cout << *input << ", "; ++input; if (empty() && verbose) cout << endl; return *this; } bool empty() const { return input.empty(); } }; template struct shuffle { typedef typename Input::value_type value_type; Input & input; value_type current, next; bool even, is_empty; // from http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetKernighan int count_bits(stxxl::uint64 v) { int c; for (c = 0; v; c++) { v &= v - 1; } return c; } void apply_shuffle() { is_empty = input.empty(); if (!is_empty) { current = *input; ++input; if (!input.empty()) { STXXL_STATIC_ASSERT(sizeof(value_type) == 4); stxxl::uint64 combined = current; combined = combined << 32 | *input; combined = (1ul << count_bits(combined)) - 1; current = combined >> 32; next = combined; } } } shuffle(Input & _input) : input(_input), current(0), next(0), even(true), is_empty(false) { apply_shuffle(); } value_type operator * () const { return current; } shuffle & operator ++ () { even = !even; is_empty = input.empty(); if (even) { ++input; apply_shuffle(); } else { current = next; } return *this; } bool empty() const { return is_empty; } }; typedef random_generator input_generator_type; typedef Cmp cmp; typedef stxxl::stream::runs_creator runs_creator_type0; typedef runs_creator_type0::sorted_runs_type sorted_runs_type; typedef stxxl::stream::runs_merger runs_merger_type; typedef output output_type; typedef filter filter_type0; typedef filter filter_type1; typedef shuffle shuffle_type; typedef stxxl::stream::runs_creator runs_creator_type1; int main(int argc, char ** argv) { if (argc < 2) { cout << "Usage: " << argv[0] << " count [Options]\nOptions: -v \t prints elements of each iteration\n"; return EXIT_FAILURE; } stxxl::block_manager::get_instance(); verbose = (argc == 3) && !strcmp(argv[2], "-v"); stxxl::uint64 total = atoi(argv[1]); input_generator_type input_stream(total); runs_creator_type0 runs_creator(input_stream, cmp(), memory_to_use); sorted_runs_type sorted_runs = runs_creator.result(); stxxl::uint64 counter = 0; int i; for (i = 0; counter < total - 1; ++i) { if (verbose) cout << "Iteration " << i << ": "; runs_merger_type runs_merger(sorted_runs, cmp(), memory_to_use); output_type output_stream(runs_merger); filter_type0 filter0(output_stream, 0, counter); filter_type1 filter1(filter0, filter_type1::value_type(-1), counter); shuffle_type shuffled_stream(filter1); runs_creator_type1 runs_creator(shuffled_stream, cmp(), memory_to_use); sorted_runs = runs_creator.result(); } runs_merger_type runs_merger(sorted_runs, cmp(), memory_to_use); while (!runs_merger.empty()) { if (verbose) cout << "Iteration " << i << ": " << *runs_merger << endl; ++runs_merger; } cout << "\nIteration needed: " << i << endl; } // vim: et:ts=4:sw=4 stxxl-1.3.1/stream/test_stream.cpp0000644000175000017500000001452611535151017017052 0ustar andreasandreas/*************************************************************************** * stream/test_stream.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2003 Roman Dementiev * Copyright (C) 2007 Andreas Beckmann * Copyright (C) 2009, 2010 Johannes Singler * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ //! \example stream/test_stream.cpp //! This is an example of how to use some basic algorithms from the //! stream package. The example sorts characters of a string producing an //! array of sorted tuples (character, index position). #include #include #include #include #define USE_FORMRUNS_N_MERGE // comment if you want to use one 'sort' algorithm // without producing intermediate sorted runs. #define USE_EXTERNAL_ARRAY // comment if you want to use internal vectors as // input/output of the algorithm #define block_size (8 * 1024) typedef stxxl::tuple tuple_type; namespace std { std::ostream & operator << (std::ostream & os, const tuple_type & t) { os << "<" << t.first << "," << t.second << ">"; return os; } } #ifdef USE_EXTERNAL_ARRAY typedef stxxl::VECTOR_GENERATOR::result input_array_type; typedef stxxl::VECTOR_GENERATOR::result output_array_type; #else typedef std::vector input_array_type; typedef std::vector output_array_type; #endif using stxxl::stream::streamify; using stxxl::stream::streamify_traits; using stxxl::stream::make_tuple; using stxxl::tuple; const char * phrase = "Hasta la vista, baby"; template void fill_input_array(Container_ & container, It_ p) { while (*p) { container.push_back(*p); ++p; } } template struct counter { typedef ValTp value_type; value_type cnt; counter() : cnt(0) { } value_type operator () () { value_type ret = cnt; ++cnt; return ret; } }; typedef counter counter_type; struct cmp_type : std::binary_function { typedef tuple_type value_type; bool operator () (const value_type & a, const value_type & b) const { return a.first < b.first; } value_type min_value() const { return value_type((std::numeric_limits::min)(), 0); } value_type max_value() const { return value_type((std::numeric_limits::max)(), 0); } }; struct cmp_int : std::binary_function { typedef int value_type; bool operator () (const value_type & a, const value_type & b) const { return a > b; } value_type max_value() const { return (((std::numeric_limits::min))()); } value_type min_value() const { return (((std::numeric_limits::max))()); } }; template struct identity : std::unary_function { typedef T value_type; const T & operator () (const T & t) { return t; } }; int main() { input_array_type input; output_array_type output; stxxl::stats * s = stxxl::stats::get_instance(); std::cout << *s; fill_input_array(input, phrase); output.resize(input.size()); // HERE streaming part begins (streamifying) // create input stream #ifdef BOOST_MSVC typedef streamify_traits::stream_type input_stream_type; #else typedef __typeof__(streamify(input.begin(), input.end())) input_stream_type; #endif input_stream_type input_stream = streamify(input.begin(), input.end()); // create counter stream #ifdef BOOST_MSVC typedef stxxl::stream::generator2stream counter_stream_type; #else typedef __typeof__(streamify(counter_type())) counter_stream_type; #endif counter_stream_type counter_stream = streamify(counter_type()); // create tuple stream typedef make_tuple tuple_stream_type; tuple_stream_type tuple_stream(input_stream, counter_stream); const stxxl::unsigned_type sorter_memory = 128 * 1024; #ifdef USE_FORMRUNS_N_MERGE // sort tuples by character // 1. form runs typedef stxxl::stream::runs_creator runs_creator_stream_type; runs_creator_stream_type runs_creator_stream(tuple_stream, cmp_type(), sorter_memory); // 2. merge runs typedef stxxl::stream::runs_merger sorted_stream_type; sorted_stream_type sorted_stream(runs_creator_stream.result(), cmp_type(), sorter_memory); #else // sort tuples by character // (combination of the previous two steps in one algorithm: form runs and merge) typedef stxxl::stream::sort sorted_stream_type; sorted_stream_type sorted_stream(tuple_stream, cmp_type(), sorter_memory); #endif typedef stxxl::stream::transform >, sorted_stream_type> transformed_stream_type; identity > id; transformed_stream_type transformed_stream(id, sorted_stream); // HERE streaming part ends (materializing) output_array_type::iterator o = stxxl::stream::materialize(transformed_stream, output.begin(), output.end()); // or materialize(sorted_stream,output.begin()); assert(o == output.end()); STXXL_MSG("input string (character,position) :"); for (unsigned i = 0; i < input.size(); ++i) { STXXL_MSG("('" << input[i] << "'," << i << ")"); } STXXL_MSG("sorted tuples (character,position):"); for (unsigned i = 0; i < input.size(); ++i) { STXXL_MSG("('" << output[i].first << "'," << output[i].second << ")"); } std::cout << *s; std::vector InternalArray(1024 * 1024); std::sort(InternalArray.begin(), InternalArray.end(), cmp_int()); //convenience function based on streaming stxxl::sort<1024 * 1024>(InternalArray.begin(), InternalArray.end(), cmp_int(), 1024 * 1024 * 31, stxxl::RC()); return 0; } stxxl-1.3.1/stream/test_stream1.cpp0000644000175000017500000000531111312162754017126 0ustar andreasandreas/*************************************************************************** * stream/test_stream1.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2003 Roman Dementiev * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #include #include struct Input { typedef unsigned value_type; value_type value; value_type rnd_value; stxxl::random_number32 rnd; value_type crc; Input(value_type init) : value(init) { rnd_value = rnd(); crc = rnd_value; } bool empty() const { return value == 1; } Input & operator ++ () { --value; rnd_value = rnd(); if (!empty()) crc += rnd_value; return *this; } const value_type & operator * () const { return rnd_value; } }; struct Cmp : std::binary_function { typedef unsigned value_type; bool operator () (const value_type & a, const value_type & b) const { return a < b; } value_type min_value() const { return (std::numeric_limits::min)(); } value_type max_value() const { return (std::numeric_limits::max)(); } }; #define MULT (1000) int main() { typedef stxxl::stream::runs_creator CreateRunsAlg; typedef CreateRunsAlg::sorted_runs_type SortedRunsType; stxxl::stats * s = stxxl::stats::get_instance(); std::cout << *s; STXXL_MSG("Size of block type " << sizeof(CreateRunsAlg::block_type)); unsigned size = MULT * 1024 * 128 / (sizeof(Input::value_type) * 2); Input in(size + 1); CreateRunsAlg SortedRuns(in, Cmp(), 1024 * 128 * MULT); SortedRunsType Runs = SortedRuns.result(); assert(stxxl::stream::check_sorted_runs(Runs, Cmp())); // merge the runs stxxl::stream::runs_merger merger(Runs, Cmp(), MULT * 1024 * 128); stxxl::vector array; STXXL_MSG(size << " " << Runs.elements); STXXL_MSG("CRC: " << in.crc); Input::value_type crc(0); for (unsigned i = 0; i < size; ++i) { //STXXL_MSG(*merger<< " must be "<< i+2 << ((*merger != i+2)?" WARNING":"")); //assert(*merger == i+2); crc += *merger; array.push_back(*merger); ++merger; } STXXL_MSG("CRC: " << crc); assert(stxxl::is_sorted(array.begin(), array.end(), Cmp())); assert(merger.empty()); std::cout << *s; return 0; } stxxl-1.3.1/stream/Makefile0000644000175000017500000000411411535663467015465 0ustar andreasandreasinclude Makefile.common include ../make.settings tests: $(TESTS) #tests: $(TESTS_NON_MSVC) DEPENDENCIES = $(COMMON_FILES) $(IO_LAYER_FILES) $(MNG_LAYER_FILES) \ $(CONTAINER_FILES) $(ALGO_FILES) $(STREAM_FILES) test_stream1: test_stream1.$(EXEEXT) test_stream1.$(EXEEXT): test_stream1.cpp $(DEPENDENCIES) $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c test_stream1.cpp -DSTXXL_VERBOSE_LEVEL=1 $(LINKER) test_stream1.$(OBJEXT) $(OUT)test_stream1.$(EXEEXT) $(STXXL_LINKER_OPTIONS) test_sorted_runs: test_sorted_runs.$(EXEEXT) test_sorted_runs.$(EXEEXT): test_sorted_runs.cpp $(DEPENDENCIES) $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c test_sorted_runs.cpp $(LINKER) test_sorted_runs.$(OBJEXT) $(OUT)test_sorted_runs.$(EXEEXT) $(STXXL_LINKER_OPTIONS) test_push_sort: test_push_sort.$(EXEEXT) test_push_sort.$(EXEEXT): test_push_sort.cpp $(DEPENDENCIES) $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c test_push_sort.cpp $(LINKER) test_push_sort.$(OBJEXT) $(OUT)test_push_sort.$(EXEEXT) $(STXXL_LINKER_OPTIONS) test_stream: test_stream.$(EXEEXT) test_stream.$(EXEEXT): test_stream.cpp $(DEPENDENCIES) $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c test_stream.cpp -DSTXXL_VERBOSE_LEVEL=1 $(LINKER) test_stream.$(OBJEXT) $(OUT)test_stream.$(EXEEXT) $(STXXL_LINKER_OPTIONS) test_materialize: test_materialize.$(EXEEXT) test_materialize.$(EXEEXT): test_materialize.cpp $(DEPENDENCIES) $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c test_materialize.cpp -DSTXXL_VERBOSE_LEVEL=1 $(LINKER) test_materialize.$(OBJEXT) $(OUT)test_materialize.$(EXEEXT) $(STXXL_LINKER_OPTIONS) test_naive_transpose: test_naive_transpose.$(EXEEXT) test_naive_transpose.$(EXEEXT): test_naive_transpose.cpp $(DEPENDENCIES) $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c test_naive_transpose.cpp $(LINKER) test_naive_transpose.$(OBJEXT) $(OUT)test_naive_transpose.$(EXEEXT) $(STXXL_LINKER_OPTIONS) test_loop: test_loop.$(EXEEXT) test_loop.$(EXEEXT): test_loop.cpp $(DEPENDENCIES) $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c test_loop.cpp $(LINKER) test_loop.$(OBJEXT) $(OUT)test_loop.$(EXEEXT) $(STXXL_LINKER_OPTIONS) clean: $(RM) $(CLEAN_TARGETS) stxxl-1.3.1/Makefile.subdir.gnu0000644000175000017500000000357411513611117016237 0ustar andreasandreas############################################################################ # Makefile.subdir.gnu # # Part of the STXXL. See http://stxxl.sourceforge.net # # Copyright (C) 2007-2010 Andreas Beckmann # # Distributed under the Boost Software License, Version 1.0. # (See accompanying file LICENSE_1_0.txt or copy at # http://www.boost.org/LICENSE_1_0.txt) ############################################################################ include $(TOPDIR)/make.settings TEST_BINARIES = $(TESTS) $(TESTS-yes) $(TESTS-yesyes) SKIPPED_TEST_BINARIES = $(TESTS-) $(TESTS-no) $(TESTS-yesno) $(TESTS-noyes) $(TESTS-nono) tests: $(TEST_BINARIES:%=%.$(bin)) lib: $(LIB_SRC:.cpp=.$(lo)) clean:: $(RM) *.$(lo) *.$o $(RM) *.$(lo:.o=).d *.$(o:.o=).d *.dT $(RM) $(TEST_BINARIES:=.$(bin)) $(RM) $(SKIPPED_TEST_BINARIES:=.$(bin)) -include *.d # Work around compiler bugs: compiler_version := $(shell $(COMPILER) -v 2>&1 | tr ' ' '_') bitness := $(shell file ../common/version.$(lo) 2>/dev/null) #debug_override_opt ?= $(warning "DBGOO: $1") debug_override_opt ?= # usage: e.g. $(call needs_override,gcc_version_4.2,32-bit,3,[-g|any|none]) needs_override ?= $(call debug_override_opt,$1%$(compiler_version);$2%$(bitness);$3%$(OPT_LEVEL);$4%$(DEBUG))\ $(and $(findstring $1,$(compiler_version)),\ $(or $(filter any,$2),$(filter $2,$(bitness))),\ $(filter $3,$(OPT_LEVEL)),\ $(or $(filter any,$4),$(if $(filter none,$4),$(if $(DEBUG),,empty)),$(filter $4,$(DEBUG)))) # usage: $(call apply_override yes|$(EMPTY),to,target) apply_override ?= $(call debug_override_opt,enable=$1;to=$2;target=$3)\ $(if $(strip $1),$3: OPT_LEVEL=$2,) # usage: $(call reduce_optimization,from,to,target,compiler,bits,debug[,type]) reduce_optimization ?= $(call apply_override,$(call needs_override,$4,$5,$1,$6),$2,$3.$($(or $(strip $7),bin))) .SECONDARY: .PHONY: tests lib clean stxxl-1.3.1/GNUmakefile.mk0000644000175000017500000000615611531237734015210 0ustar andreasandreas############################################################################ # GNUmakefile.mk # # Part of the STXXL. See http://stxxl.sourceforge.net # # Copyright (C) 2007-2010 Andreas Beckmann # # Distributed under the Boost Software License, Version 1.0. # (See accompanying file LICENSE_1_0.txt or copy at # http://www.boost.org/LICENSE_1_0.txt) ############################################################################ # # HowTo use GNUmakefile.mk: create a sample GNUmakefile using the command # # make -f GNUmakefile.mk GNUmakefile # # then edit it to override MODE, NICE (if you want) # and select your favorite subset of targets MODE ?= g++ MODE ?= icpc NICE ?= nice PMODE ?= parallel_mode # undefine to disable MCSTL ?= mcstl # undefine to disable MODESUFFIX = $(shell $(MAKE) -f Makefile.gnu getmodesuffix 2>/dev/null || true) default-all: lib tests header-compile-test lib: dep-check-sanity $(MAKE) -f Makefile library_$(MODE) $(if $(PMODE),library_$(MODE)_pmode) $(if $(MCSTL),library_$(MODE)_mcstl) tests: lib $(NICE) $(MAKE) -f Makefile tests_$(MODE) $(if $(PMODE),tests_$(MODE)_pmode) $(if $(MCSTL),tests_$(MODE)_mcstl) find . -name \*.d -exec grep -H '\.\..*:' {} + ; test $$? = 1 localtests: lib $(NICE) $(MAKE) -f Makefile tests_$(MODE) $(if $(PMODE),tests_$(MODE)_pmode) $(if $(MCSTL),tests_$(MODE)_mcstl) SUBDIRS=local localclean: $(MAKE) -C local clean examples: lib $(MAKE) -C doc/tutorial/examples clean $(MAKE) -C doc/tutorial/examples all STXXL_MK=stxxl$(MODESUFFIX).mk header-compile-test: lib $(NICE) $(MAKE) -C test/compile-stxxl-headers INSTANCE=stxxl$(MODESUFFIX) $(if $(PMODE),$(NICE) $(MAKE) -C test/compile-stxxl-headers INSTANCE=pmstxxl$(MODESUFFIX)) $(if $(MCSTL),$(NICE) $(MAKE) -C test/compile-stxxl-headers INSTANCE=mcstxxl$(MODESUFFIX)) do-run-all-tests: @test -n "$(STXXL_TMPDIR)" || ( echo "STXXL_TMPDIR is not set"; exit 1 ) @test -z "$(LD_PRELOAD)" || ( echo "LD_PRELOAD is set"; exit 1 ) ./misc/run-all-tests stxxl$(MODESUFFIX) $(WITH_VALGRIND) $(WITH_VALGRIND) $(if $(MCSTL),./misc/run-all-tests mcstxxl$(MODESUFFIX) $(WITH_VALGRIND) $(WITH_VALGRIND)) $(if $(PMODE),./misc/run-all-tests pmstxxl$(MODESUFFIX) $(WITH_VALGRIND) $(WITH_VALGRIND)) run-all-tests: WITH_VALGRIND=no run-all-tests: do-run-all-tests ; run-all-tests-valgrind: WITH_VALGRIND=yes run-all-tests-valgrind: do-run-all-tests ; dep-check-sanity: $(SKIP_SANITY_CHECK)find . -name '*.o' -exec misc/remove-unless {} .o .d \; $(SKIP_SANITY_CHECK)find . -name '*.bin' -exec misc/remove-unless {} .bin .o \; clean: $(MAKE) -f Makefile clean_$(MODE) clean_$(MODE)_pmode clean_$(MODE)_mcstl clean_doxy clean_examples $(MAKE) -C test/compile-stxxl-headers clean GNUmakefile: echo "" > $@ echo "#MODE=g++" >> $@ echo "#MODE=icpc" >> $@ echo "#NICE=" >> $@ echo "#PMODE=#empty" >> $@ echo "#MCSTL=#empty" >> $@ echo "" >> $@ echo "all: lib header-compile-test tests" >> $@ echo " @echo ALL DONE" >> $@ echo "" >> $@ echo "-include make.settings.local" >> $@ echo "include GNUmakefile.mk" >> $@ %:: $(MAKE) -f Makefile $@ .PHONY: all default-all lib tests header-compile-test clean stxxl-1.3.1/LICENSE_1_0.txt0000644000175000017500000000247211024224060014770 0ustar andreasandreasBoost Software License - Version 1.0 - August 17th, 2003 Permission is hereby granted, free of charge, to any person or organization obtaining a copy of the software and accompanying documentation covered by this license (the "Software") to use, reproduce, display, distribute, execute, and transmit the Software, and to prepare derivative works of the Software, and to permit third-parties to whom the Software is furnished to do so, all subject to the following: The copyright notices in the Software and this entire statement, including the above license grant, this restriction and the following disclaimer, must be included in all copies of the Software, in whole or in part, and all derivative works of the Software, unless such copies or derivative works are solely in the form of machine-executable object code generated by a source language processor. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. stxxl-1.3.1/make.settings.gnu0000644000175000017500000003655211535563072016023 0ustar andreasandreas# This -*- Makefile -*- is intended for processing with GNU make. ############################################################################ # make.settings.gnu # # Part of the STXXL. See http://stxxl.sourceforge.net # # Copyright (C) 2002-2007 Roman Dementiev # Copyright (C) 2006-2010 Johannes Singler # Copyright (C) 2007-2011 Andreas Beckmann # # Distributed under the Boost Software License, Version 1.0. # (See accompanying file LICENSE_1_0.txt or copy at # http://www.boost.org/LICENSE_1_0.txt) ############################################################################ TOPDIR ?= $(error TOPDIR not defined) # DO NOT CHANGE! This is set elsewhere. # Change this file according to your paths. # Instead of modifying this file, you could also set your modified variables # in make.settings.local (needs to be created first, a template can be created # by running 'make config_gnu'). -include $(TOPDIR)/make.settings.local USE_BOOST ?= no # set 'yes' to use Boost libraries or 'no' to not use Boost libraries USE_MACOSX ?= no # set 'yes' if you run Mac OS X, 'no' otherwise USE_FREEBSD ?= no # set 'yes' if you run FreeBSD, 'no' otherwise USE_PARALLEL_MODE ?= no # set 'yes' to explicitly enable parallel mode for stxxl operations only ENABLE_SHARED ?= no # set 'yes' to build a shared library instead of a static library (EXPERIMENTAL) # internal flags USE_PMODE ?= no # will be overridden from main Makefile USE_MCSTL ?= no # will be overridden from main Makefile USE_ICPC ?= no # will be overridden from main Makefile STXXL_ROOT ?= $(TOPDIR) ifeq ($(strip $(USE_ICPC)),yes) COMPILER_ICPC ?= icpc COMPILER ?= $(COMPILER_ICPC) #ICPC_GCC ?= gcc-x.y # override the gcc/g++ used to find headers and libraries WARNINGS ?= -Wall -w1 -openmp-report0 -vec-report0 endif ifeq ($(strip $(USE_PMODE)),yes) COMPILER_GCC ?= g++-4.4.x MODEBASE ?= pmstxxl endif ifeq ($(strip $(USE_MCSTL)),yes) COMPILER_GCC ?= g++-4.2.3 MODEBASE ?= mcstxxl # the root directory of your MCSTL installation MCSTL_ROOT ?= $(HOME)/work/mcstl endif ifeq ($(strip $(USE_BOOST)),yes) #BOOST_ROOT ?= /usr/local/boost-1.34.1 LIBEXTRA ?= _boost endif COMPILER_GCC ?= g++ COMPILER ?= $(COMPILER_GCC) LINKER ?= $(COMPILER) OPT_LEVEL ?= 3 OPT ?= -O$(OPT_LEVEL) # compiler optimization level WARNINGS ?= -W -Wall -Woverloaded-virtual -Wundef DEBUG ?= # put here -g option to include the debug information into the binaries LIBBASE ?= stxxl LIBEXTRA ?= MODEBASE ?= stxxl LIBNAME ?= $(LIBBASE)$(LIBEXTRA) MODENAME ?= $(MODEBASE)$(LIBEXTRA) # Hint: for g++-4.4 with c++0x support, enable the following: #STXXL_SPECIFIC += -std=c++0x #### TROUBLESHOOTING # # For automatical checking of order of the output elements in # the sorters: stxxl::stream::sort, stxxl::stream::merge_runs, # stxxl::sort, and stxxl::ksort use # #STXXL_SPECIFIC += -DSTXXL_CHECK_ORDER_IN_SORTS # # If your program aborts with message "read/write: wrong parameter" # or "Invalid argument" # this could be that your kernel does not support direct I/O # then try to set it off recompiling the libs and your code with option # #STXXL_SPECIFIC += -DSTXXL_DIRECT_IO_OFF # # But for the best performance it is strongly recommended # to reconfigure the kernel for the support of the direct I/O. #### You usually shouldn't need to change the sections below ##### #### MACOSX CONFIGURATION ######################################## ifeq ($(strip $(USE_MACOSX)),yes) PTHREAD_FLAG ?= GET_FILE_ID ?= stat -L -f '%d:%i' $1 endif ################################################################## #### FREEBSD CONFIGURATION ####################################### ifeq ($(strip $(USE_FREEBSD)),yes) PTHREAD_FLAG ?= -pthread GET_FILE_ID ?= stat -L -f '%d:%i' $1 endif ################################################################## #### LINUX (DEFAULT) CONFIGURATION ############################### PTHREAD_FLAG ?= -pthread # get a unique identifier for a file or directory, # e.g. device number + inode number GET_FILE_ID ?= stat -L -c '%d:%i' $1 ################################################################## #### SHARED LIBRARY ############################################### ifeq ($(strip $(ENABLE_SHARED)),yes) LIBEXT ?= so LIBGEN ?= false # see lib/GNUmakefile STXXL_LIBRARY_SPECIFIC += -fPIC endif ################################################################### #### STXXL CONFIGURATION ######################################### # create make.settings.local in the root directory ifneq (,$(strip $(wildcard $(CURDIR)/include/stxxl.h))) ifeq (,$(strip $(wildcard $(CURDIR)/make.settings.local))) ifeq (,$(STXXL_AUTOCONFIG)) $(warning *** WARNING: you did not have a make.settings.local file -- creating ...) endif cmt = \# $(shell echo '$(cmt)STXXL_ROOT = $(CURDIR:$(HOME)%=$$(HOME)%)' >> $(CURDIR)/make.settings.local) MCSTL_ROOT ?= $(HOME)/work/mcstl $(shell echo '$(cmt)MCSTL_ROOT = $(MCSTL_ROOT:$(HOME)%=$$(HOME)%)' >> $(CURDIR)/make.settings.local) $(shell echo '$(cmt)COMPILER_GCC = g++' >> $(CURDIR)/make.settings.local) $(shell echo '$(cmt)COMPILER_GCC = g++-4.4 -std=c++0x' >> $(CURDIR)/make.settings.local) $(shell echo '$(cmt)COMPILER_ICPC = icpc' >> $(CURDIR)/make.settings.local) $(shell echo '$(cmt)USE_BOOST = no' >> $(CURDIR)/make.settings.local) $(shell echo '$(cmt)BOOST_ROOT = ' >> $(CURDIR)/make.settings.local) $(shell echo '$(cmt)USE_PARALLEL_MODE = no' >> $(CURDIR)/make.settings.local) ifeq (Darwin,$(strip $(shell uname))) $(shell echo 'USE_MACOSX = yes' >> $(CURDIR)/make.settings.local) else $(shell echo '$(cmt)USE_MACOSX = no' >> $(CURDIR)/make.settings.local) endif ifeq (FreeBSD,$(strip $(shell uname))) $(shell echo 'USE_FREEBSD = yes' >> $(CURDIR)/make.settings.local) else $(shell echo '$(cmt)USE_FREEBSD = no' >> $(CURDIR)/make.settings.local) endif include make.settings.local endif endif # check, whether stxxl is configured correctly ifeq (,$(strip $(wildcard $(STXXL_ROOT)/include/stxxl.h))) $(warning *** WARNING: STXXL has not been configured correctly) $(warning *** WARNING: Please check make.settings.local) $(error ERROR: could not find a STXXL installation in STXXL_ROOT=$(STXXL_ROOT)) endif # in the top dir, check whether STXXL_ROOT points to ourselves ifneq (,$(wildcard make.settings)) stat1 = $(shell $(call GET_FILE_ID, ./)) stat2 = $(shell $(call GET_FILE_ID, $(STXXL_ROOT)/)) ifneq ($(stat1),$(stat2)) $(error ERROR: STXXL_ROOT=$(STXXL_ROOT) points to a different STXXL installation) endif endif ################################################################## #### STXXL OPTIONS ############################################### STXXL_SPECIFIC += \ $(PTHREAD_FLAG) \ $(CPPFLAGS_ARCH) \ -I$(strip $(STXXL_ROOT))/include \ -include stxxl/bits/defines.h \ -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE STXXL_LIBRARY_SPECIFIC += -D_IN_LIBSTXXL STXXL_LDFLAGS += $(PTHREAD_FLAG) STXXL_LDLIBS += -L$(strip $(STXXL_ROOT))/lib -l$(LIBNAME) STXXL_LIBDEPS += $(strip $(STXXL_ROOT))/lib/lib$(LIBNAME).$(LIBEXT) UNAME_M := $(shell uname -m) CPPFLAGS_ARCH += $(CPPFLAGS_$(UNAME_M)) CPPFLAGS_i686 ?= -march=i686 ################################################################## #### ICPC OPTIONS ################################################ ifeq ($(strip $(USE_ICPC)),yes) OPENMPFLAG ?= -openmp ICPC_CPPFLAGS += $(if $(ICPC_GCC),-gcc-name=$(strip $(ICPC_GCC))) ICPC_LDFLAGS += $(if $(ICPC_GCC),-gcc-name=$(strip $(ICPC_GCC))) STXXL_SPECIFIC += -include bits/intel_compatibility.h endif ################################################################## #### PARALLEL_MODE OPTIONS ############################################### ifeq ($(strip $(USE_PMODE)),yes) OPENMPFLAG ?= -fopenmp PARALLEL_MODE_CPPFLAGS += $(OPENMPFLAG) -D_GLIBCXX_PARALLEL PARALLEL_MODE_LDFLAGS += $(OPENMPFLAG) else ifeq ($(strip $(USE_PARALLEL_MODE)),yes) OPENMPFLAG ?= -fopenmp EXPLICIT_PARALLEL_MODE_CPPFLAGS += $(OPENMPFLAG) -DSTXXL_PARALLEL_MODE_EXPLICIT EXPLICIT_PARALLEL_MODE_LDFLAGS += $(OPENMPFLAG) STXXL_SPECIFIC += $(EXPLICIT_PARALLEL_MODE_CPPFLAGS) STXXL_LDFLAGS += $(EXPLICIT_PARALLEL_MODE_LDFLAGS) endif endif ################################################################## #### MCSTL OPTIONS ############################################### ifeq ($(strip $(USE_MCSTL)),yes) OPENMPFLAG ?= -fopenmp ifeq (,$(strip $(wildcard $(strip $(MCSTL_ROOT))/c++/mcstl.h))) $(error ERROR: could not find a MCSTL installation in MCSTL_ROOT=$(MCSTL_ROOT)) endif MCSTL_CPPFLAGS += $(OPENMPFLAG) -D__MCSTL__ -I$(MCSTL_ROOT)/c++ MCSTL_LDFLAGS += $(OPENMPFLAG) endif ################################################################## #### BOOST OPTIONS ############################################### BOOST_INCLUDE ?= $(if $(strip $(BOOST_ROOT)),$(strip $(BOOST_ROOT))/include) BOOST_COMPILER_OPTIONS += $(foreach inc,$(BOOST_INCLUDE),-I$(inc)) BOOST_COMPILER_OPTIONS += -DSTXXL_BOOST_CONFIG BOOST_COMPILER_OPTIONS += -DSTXXL_BOOST_FILESYSTEM BOOST_COMPILER_OPTIONS += -DSTXXL_BOOST_RANDOM BOOST_COMPILER_OPTIONS += -DSTXXL_BOOST_THREADS #BOOST_COMPILER_OPTIONS += -DSTXXL_BOOST_TIMESTAMP # probably less efficient than gettimeofday() BOOST_LIB_PATH ?= $(if $(strip $(BOOST_ROOT)),$(strip $(BOOST_ROOT))/lib) BOOST_LIB_COMPILER_SUFFIX ?= BOOST_LIB_MT_SUFFIX ?= -mt BOOST_LINKER_OPTIONS = \ $(foreach lib,$(BOOST_LIB_PATH),-L$(lib)) \ -lboost_thread$(BOOST_LIB_COMPILER_SUFFIX)$(BOOST_LIB_MT_SUFFIX) \ -lboost_date_time$(BOOST_LIB_COMPILER_SUFFIX)$(BOOST_LIB_MT_SUFFIX) \ -lboost_iostreams$(BOOST_LIB_COMPILER_SUFFIX)$(BOOST_LIB_MT_SUFFIX) \ -lboost_system$(BOOST_LIB_COMPILER_SUFFIX)$(BOOST_LIB_MT_SUFFIX) \ -lboost_filesystem$(BOOST_LIB_COMPILER_SUFFIX)$(BOOST_LIB_MT_SUFFIX) ################################################################## #### CPPUNIT OPTIONS ############################################# CPPUNIT_COMPILER_OPTIONS += CPPUNIT_LINKER_OPTIONS += -lcppunit -ldl ################################################################## #### DEPENDENCIES ################################################ HEADER_FILES_BITS += namespace.h noncopyable.h version.h HEADER_FILES_BITS += compat_hash_map.h HEADER_FILES_BITS += compat_unique_ptr.h parallel.h singleton.h defines.h HEADER_FILES_BITS += verbose.h unused.h HEADER_FILES_BITS += msvc_compatibility.h deprecated.h libstxxl.h HEADER_FILES_COMMON += aligned_alloc.h new_alloc.h HEADER_FILES_COMMON += mutex.h rand.h semaphore.h state.h HEADER_FILES_COMMON += timer.h utils.h error_handling.h simple_vector.h HEADER_FILES_COMMON += switch.h tmeta.h log.h exceptions.h tuple.h HEADER_FILES_COMMON += types.h settings.h seed.h is_sorted.h exithandler.h HEADER_FILES_COMPAT += shared_ptr.h HEADER_FILES_COMPAT += type_traits.h HEADER_FILES_IO += io.h iostats.h completion_handler.h HEADER_FILES_IO += request_interface.h HEADER_FILES_IO += request.h HEADER_FILES_IO += request_ptr.h HEADER_FILES_IO += request_operations.h HEADER_FILES_IO += request_with_state.h HEADER_FILES_IO += request_with_waiters.h HEADER_FILES_IO += serving_request.h HEADER_FILES_IO += disk_queues.h HEADER_FILES_IO += request_queue.h request_queue_impl_worker.h HEADER_FILES_IO += request_queue_impl_qwqr.h HEADER_FILES_IO += request_queue_impl_1q.h HEADER_FILES_IO += file.h disk_queued_file.h HEADER_FILES_IO += ufs_file_base.h syscall_file.h mmap_file.h simdisk_file.h HEADER_FILES_IO += wfs_file_base.h wincall_file.h HEADER_FILES_IO += boostfd_file.h mem_file.h fileperblock_file.h HEADER_FILES_IO += wbtl_file.h HEADER_FILES_IO += create_file.h HEADER_FILES_MNG += adaptor.h block_prefetcher.h HEADER_FILES_MNG += buf_istream.h buf_ostream.h buf_writer.h mng.h HEADER_FILES_MNG += bid.h typed_block.h diskallocator.h config.h HEADER_FILES_MNG += write_pool.h prefetch_pool.h read_write_pool.h HEADER_FILES_MNG += block_alloc.h block_alloc_interleaved.h HEADER_FILES_CONTAINERS += pager.h stack.h vector.h priority_queue.h #EADER_FILES_CONTAINERS += pq_helpers.h pq_mergers.h pq_ext_merger.h #EADER_FILES_CONTAINERS += pq_losertree.h HEADER_FILES_CONTAINERS += queue.h map.h deque.h HEADER_FILES_CONTAINERS_BTREE += btree.h iterator_map.h leaf.h node_cache.h HEADER_FILES_CONTAINERS_BTREE += root_node.h node.h iterator.h HEADER_FILES_ALGO += adaptor.h inmemsort.h intksort.h run_cursor.h sort.h HEADER_FILES_ALGO += async_schedule.h ksort.h sort_base.h sort_helper.h HEADER_FILES_ALGO += losertree.h scan.h stable_ksort.h random_shuffle.h HEADER_FILES_STREAM += stream.h sort_stream.h HEADER_FILES_STREAM += choose.h unique.h HEADER_FILES_STREAM += sorted_runs.h HEADER_FILES_UTILS += malloc.h ################################################################### #### MISC ######################################################### # extension of object files OBJEXT ?= $(MODENAME).o # extension of object files for the library LIBOBJEXT ?= lib$(LIBNAME).o IIEXT ?= $(MODENAME).ii # static library file extension LIBEXT ?= a # executable file extension EXEEXT ?= $(MODENAME).bin # static library generation LIBGEN ?= ar cr # output file option for the compiler and linker OUT ?= -o o ?= $(strip $(OBJEXT)) lo ?= $(strip $(LIBOBJEXT)) ii ?= $(strip $(IIEXT)) bin ?= $(strip $(EXEEXT)) ################################################################### #### COMPILE/LINK RULES ########################################### define COMPILE_STXXL @$(RM) $@ $(@:.o=).d $(COMPILER) $(STXXL_COMPILER_OPTIONS) -MD -MF $(@:.o=).dT -c $(OUTPUT_OPTION) $< && mv $(@:.o=).dT $(@:.o=).d endef DEPS_MAKEFILES := $(wildcard $(TOPDIR)/Makefile.subdir.gnu $(TOPDIR)/make.settings $(TOPDIR)/make.settings.local GNUmakefile Makefile Makefile.common Makefile.local) EXTRA_DEPS_COMPILE ?= $(DEPS_MAKEFILES) %.$o: %.cpp $(EXTRA_DEPS_COMPILE) $(COMPILE_STXXL) %.$(lo): PARALLEL_MODE_CPPFLAGS= %.$(lo): EXPLICIT_PARALLEL_MODE_CPPFLAGS= %.$(lo): MCSTL_CPPFLAGS= %.$(lo): STXXL_COMPILER_OPTIONS += $(STXXL_LIBRARY_SPECIFIC) %.$(lo): o=$(lo) %.$(lo): %.cpp $(EXTRA_DEPS_COMPILE) $(COMPILE_STXXL) %.$(ii): %.cpp $(EXTRA_DEPS_COMPILE) $(COMPILER) $(STXXL_COMPILER_OPTIONS) -E $(OUTPUT_OPTION) $< # $1=infix $2=additional CPPFLAGS define COMPILE_VARIANT %.$1.$$o: CPPFLAGS += $2 %.$1.$$o: %.cpp $$(EXTRA_DEPS_COMPILE) $$(COMPILE_STXXL) endef LINK_STXXL = $(LINKER) $1 $(STXXL_LINKER_OPTIONS) -o $@ %.$(bin): %.$o $(STXXL_LIBDEPS) $(call LINK_STXXL, $<) # last resort rules to ignore header files missing due to renames etc. $(STXXL_ROOT)/include/%:: @echo "MISSING HEADER: '$@' (ignored)" %.h:: @echo "MISSING HEADER: '$@' (ignored)" /%:: @echo "MISSING FILE: '$@' (ignored)" ################################################################### STXXL_SPECIFIC += $(STXXL_EXTRA) WARNINGS += $(WARNINGS_EXTRA) ifeq ($(strip $(USE_ICPC)),yes) STXXL_CPPFLAGS_CXX += $(ICPC_CPPFLAGS) STXXL_LDLIBS_CXX += $(ICPC_LDFLAGS) endif STXXL_COMPILER_OPTIONS += $(STXXL_CPPFLAGS_CXX) STXXL_COMPILER_OPTIONS += $(STXXL_SPECIFIC) STXXL_COMPILER_OPTIONS += $(OPT) $(DEBUG) $(WARNINGS) STXXL_LINKER_OPTIONS += $(STXXL_LDLIBS_CXX) STXXL_LINKER_OPTIONS += $(DEBUG) STXXL_LINKER_OPTIONS += $(STXXL_LDFLAGS) STXXL_LINKER_OPTIONS += $(STXXL_LDLIBS) ifeq ($(strip $(USE_PMODE)),yes) STXXL_COMPILER_OPTIONS += $(PARALLEL_MODE_CPPFLAGS) STXXL_LINKER_OPTIONS += $(PARALLEL_MODE_LDFLAGS) endif ifeq ($(strip $(USE_MCSTL)),yes) STXXL_COMPILER_OPTIONS += $(MCSTL_CPPFLAGS) STXXL_LINKER_OPTIONS += $(MCSTL_LDFLAGS) endif ifeq ($(strip $(USE_BOOST)),yes) STXXL_COMPILER_OPTIONS += $(BOOST_COMPILER_OPTIONS) STXXL_LINKER_OPTIONS += $(BOOST_LINKER_OPTIONS) endif STXXL_COMPILER_OPTIONS += $(CPPFLAGS) STXXL_LINKER_OPTIONS += $(LDFLAGS) # vim: syn=make stxxl-1.3.1/doc/0000755000175000017500000000000011536252420013257 5ustar andreasandreasstxxl-1.3.1/doc/tutorial/0000755000175000017500000000000011536252420015122 5ustar andreasandreasstxxl-1.3.1/doc/tutorial/tutorial.tex0000644000175000017500000023175511437170637017535 0ustar andreasandreas\documentclass[twoside]{book} %\usepackage{algorithmic} %\usepackage{eepic} %\usepackage{epic} \usepackage{amsmath} \usepackage{amssymb} \usepackage{latexsym} \usepackage{times} \usepackage{mathptm} \usepackage{bbold} \usepackage{comment} \usepackage{epsfig} %\usepackage{fancyheadings} \usepackage{fancyhdr} \usepackage{float} %Floatflt was apparently removed for licencing problems. %http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=565457 %\usepackage{floatflt} \usepackage{graphics} \usepackage{moreverb} \usepackage{epic} \usepackage{eepic} \usepackage{theorem} \usepackage{url} %\usepackage{html} \usepackage{listings} \usepackage{graphicx} \hoffset=-1in \voffset=-1in %-- Textbreite \setlength{\textwidth}{120mm} % 9/12 * 160mm \setlength{\oddsidemargin}{23.3mm} % 1/12 * 160mm + 10 ungesehene \setlength{\evensidemargin}{26.6mm} % 2/12 * 160mm %-- Texthoehe %\setlength{\textheight}{180mm} % 9/12 * 240mm \setlength{\textheight}{220mm} % 9/12 * 240mm \setlength{\topmargin}{20mm} % 1/12 * 240mm \addtolength{\textheight}{-\headheight} \addtolength{\textheight}{-\headsep} \hfuzz 1.5pt \renewcommand{\topfraction}{0.999} \renewcommand{\bottomfraction}{0.999} \renewcommand{\textfraction}{0.001} \pagestyle{fancyplain} \renewcommand{\chaptermark}[1]{\markboth{#1}{#1}} \renewcommand{\sectionmark}[1]{\markright{\thesection\ #1}} \lhead[\fancyplain{{\tiny Dementiev \today} \bf\thepage}{\bf\thepage}]{ \fancyplain{\rightmark}} \rhead[\fancyplain{}{\leftmark}]{\fancyplain{{\tiny Dementiev \today} \bf\thepage}{\bf\thepage}} \cfoot[{\fancyplain{}{}}]{\fancyplain{}{}} \renewcommand{\labelenumi}{\alph{enumi})} \include{allmakros} \makeindex %\newcommand{\stxxl}{{S{\small TXXL} }} %\newcommand{\stxxll}{S{\fontsize{11pt}{11pt}\selectfont TXXL} } \newcommand{\stxxl}{{\sc Stxxl} } \begin{document} \lstset{language=C++,frame=single,tabsize=4,basicstyle=\ttfamily\small, moredelim=[is][\underbar]{@}{@}} \pagenumbering{roman}% % \pagestyle{empty} \setcounter{page}{-2}% \begin{titlepage}% under development \large \vspace*{1cm} \vspace*{1cm} \vspace*{1cm} \begin{center} {\huge \stxxl Tutorial}\\ for \stxxl 1.1 \vspace{3mm} {\LARGE Roman Dementiev\\[2mm]} \vspace*{\fill} {\normalsize under development} \end{center} \thispagestyle{empty} \end{titlepage} \thispagestyle{empty} %\chapter*{Foreword} \setcounter{tocdepth}{1} \tableofcontents \clearpage \pagenumbering{arabic} % \pagestyle{empty} \setcounter{page}{1} \chapter{Introduction} There exist many application that have to process data sets which can not fit into the main memory of a computer, but external memory (e.g.\ hard disks). The examples are Geographic Information Systems, Internet and telecommunication billing systems, Information Retrieval systems manipulating terabytes of data. The most of engineering efforts have been spent on designing algorithms which work on data that \emph{completely} resides in the main memory. The algorithms assume that the execution time of any memory access is a \emph{small} constant (1--20 ns). But it is no more true when an application needs to access external memory (EM). Because of the mechanical nature of the position seeking routine, a random hard disk access takes about 3--20 ms. This is about {\bf 1~000~000} longer than a main memory access. Since the I/Os are apparently the major bottleneck of applications that handle large data sets, they minimize the number of performed I/Os. A new measure of program performance is becoming sound -- the I/O complexity. Vitter and Shriver \cite{VitShr94both} came up with a model for designing I/O efficient algorithms. In order to amortize the high cost of a random disk access\footnote{Modern disks after locating the position of the data on the surface can deliver the contiguous data blocks at speed 50-60 MiB/s. For example with the seek time 10~ms, 1~MiB can be read or written in $10~+~1000~\times~1/50~=~30$~ms, 1~byte -- in 10.02~ms.}, external data loaded in contiguous chunks of size $B$. To increase bandwidth external memory algorithms use multiple parallel disks. The algorithms try in each I/O step transfer $D$ blocks between the main memory and disks (one block per each disk). I/O efficient algorithms have been developed for many problem domains, including fundamental ones like sorting \cite{}, graph algorithms \cite{}, string processing \cite{}, computational geometry \cite{}. However there is the ever increasing gap between theoretical nouveau of external memory algorithms and their use in practice. Several EM software library projects (LEDA-SM \cite{CraMeh99} and TPIE \cite{APV02}) attempted to reduce this gap. They offer frameworks which aim to speed up the process of implementing I/O efficient algorithms giving a high level abstraction away the details of how I/O is performed. Implementations of many EM algorithms and data structures are offered as well. Those projects are excellent proofs of EM paradigm, but have some drawbacks which \emph{impede} their practical use. Therefore we started to develop \stxxl library, which tries to avoid those obstacles. The objectives of \stxxl project (distinguishing it from other libraries): \begin{itemize} \item Make the library able to handle problems of \emph{real world size} (up to dozens of terabytes). \item Offer \emph{transparent} support of parallel disks. This feature although announced has not been implemented in any library. \item Implement \emph{parallel} disk algorithms. LEDA-SM and TPIE libraries offer only implementations of single disk EM algorithms. \item Use computer resources more efficiently. \stxxl allows transparent \emph{overlapping} of I/O and computation in many algorithms and data structures. \item Care about constant factors in I/O volume. A unique library feature \emph{``pipelining''} can \emph{half} the number of I/Os performed by an algorithm. \item Care about the \emph{internal work}, improve the in-memory algorithms. Having many disks can hide the latency and increase the I/O bandwidth, s.t. internal work becomes a bottleneck. \item Care about operating system overheads. Use \emph{unbuffered disk access} to avoid superfluous copying of data. \item Shorten \emph{development times} providing well known interface for EM algorithms and data structures. We provide STL-compatible\footnote{STL -- Standard Template Library \cite{stepanov94standard} is freely available library of algorithms and data structures delivered with almost any C++ compiler.} interfaces for our implementations. \end{itemize} \chapter{Prerequisites} The intended audience of this tutorial are developers or researchers who develop applications or implement algorithms processing large data sets which do not fit into the main memory of a computer. They must have basic knowledge in the theory of external memory computing and have working knowledge of C++ and an experience with programming using STL. Familiarity with key concepts of generic programming and C++ template mechanism is assumed. \chapter{Installation} See the \stxxl home page \url{stxxl.sourceforge.net} for the installation instruction for your compiler and operating system. \chapter{A Starting Example} % A billing system for phone calls % AT&T Gecko 60G records, 2.6 TB Let us start with a toy but pretty relevant problem: the phone call billing problem. You are given a sequence of event records. Each record has a time stamp (time when the event had happened), type of event ('call begin' or 'call end'), the callers number, and the destination number. The event sequence is time-ordered. Your task is to generate a bill for each subscriber that includes cost of all her calls. The solution is uncomplicated: sort the records by the callers number. Since the sort brings all records of a subscriber together, we \emph{scan} the sorted result computing and summing up the costs of all calls of a particular subscriber. The phone companies record up to 300 million transactions per day. AT\&T billing system Gecko \cite{BillingLarge} has to process databases with about 60 billion records, occupying 2.6 terabytes. Certainly this volume can not be sorted in the main memory of a single computer\footnote{Except may be in the main memory of an expensive \emph{super}computer.}. Therefore we need to sort those huge data sets out-of-memory. Now we show how \stxxl can be useful here, since it can handle large volumes I/O efficiently. \section{STL Code} If you are familiar with STL your the {\tt main} function of bill generation program will probably look like this: \begin{lstlisting} int main(int argc, char * argv[]) { if(argc < 4) // check if all parameters are given { // in the command line print_usage(argv[0]); return 0; } // open file with the event log std::fstream in(argv[1],std::ios::in); // create a vector of log entries to read in std::vector v; // read the input file and push the records // into the vector std::copy(std::istream_iterator(in), std::istream_iterator(), std::back_inserter(v)); // sort records by callers number std::sort(v.begin(),v.end(),SortByCaller()); // open bill file for output std::fstream out(argv[3],std::ios::out); // scan the vector and output bills std::for_each(v.begin(),v.end(),ProduceBill(out)); return 0; } \end{lstlisting} To complete the code we need to define the log entry data type {\tt LogEntry}, input operator {\tt >>} for {\tt LogEntry}, comparison functor {\tt SortByCaller}, unary functor {\tt ProduceBills} used for computing bills, and the {\tt print\_usage} function. \begin{lstlisting} #include // for STL std::sort #include // for STL std::vector #include // for std::fstream #include #include // for time_t type #define CT_PER_MIN 2 // subscribers pay 2 cent per minute struct LogEntry // the event log data structure { long long int from; // callers number (64 bit integer) long long int to; // destination number (64 bit int) time_t timestamp; // time of event int event; // event type 1 - call started // 2 - call ended }; // input operator used for reading from the file std::istream & operator >> (std::istream & i, LogEntry & entry) { i >> entry.from; i >> entry.to; i >> entry.timestamp; i >> entry.event; return i; } struct SortByCaller // comparison function { bool operator() ( const LogEntry & a, const LogEntry & b) const { return a.from < b.from || (a.from == b.from && a.timestamp < b.timestamp) || (a.from == b.from && a.timestamp == b.timestamp && a.event < b.event); } static LogEntry min_value() { LogEntry dummy; dummy.from = (std::numeric_limits::min)(); return dummy; } static LogEntry max_value() { LogEntry dummy; dummy.from = (std::numeric_limits::max)(); return dummy; } } // unary function used for producing the bills struct ProduceBill { std::ostream & out; // stream for outputting // the bills unsigned sum; // current subscribers debit LogEntry last; // the last record ProduceBill(std::ostream & o_):out(o_),sum(0) { last.from = -1; } void operator () (const LogEntry & e) { if(last.from == e.from) { // either the last event was 'call started' // and current event is 'call ended' or the // last event was 'call ended' and current // event is 'call started' assert( (last.event == 1 && e.event == 2) || (last.event == 2 && e.event == 1)); if(e.event == 2) // call ended sum += CT_PER_MIN* (e.timestamp - last.timestamp)/60; } else if(last.from != -1) { // must be 'call ended' assert(last.event == 2); // must be 'call started' assert(e.event == 1); // output the total sum out << last.from <<"; "<< (sum/100)<<" EUR " << (sum%100)<< " ct"<< std::endl; sum = 0; // reset the sum } last = e; } }; void print_usage(const char * program) { std::cout << "Usage: "<@ // the rest of the code remains the same int main(int argc, char * argv[]) { if(argc < 4) // check if all parameters are given { // in the command line print_usage(argv[0]); return 0; } // open file with the event log std::fstream in(argv[1],std::ios::in); // create a vector of log entries to read in @stxxl@::vector v; // read the input file and push the records // into the vector std::copy(std::istream_iterator(in), std::istream_iterator(), std::back_inserter(v)); // bound the main memory consumption by M // during sorting const unsigned M = atol(argv[2])*1024*1024; // sort records by callers number @stxxl@::sort(v.begin(),v.end(),SortByCaller()@,M@); // open bill file for output std::fstream out(argv[3],std::ios::out); // scan the vector and output bills // the last parameter tells how many buffers // to use for overlapping I/O and computation @stxxl@::for_each(v.begin(),v.end(),ProduceBill(out)@,2@); return 0; } \end{lstlisting} As you note the changes are minimal. Only the namespaces and some memory specific parameters had to be changed. To compile the \stxxl billing program you may use the following {\tt Makefile}: \begin{verbatim} all: phonebills # path to stxxl.mk file # from your stxxl installation include ~/stxxl/stxxl.mk phonebills: phonebills.cpp $(STXXL_CXX) -c phonebills.cpp $(STXXL_CPPFLAGS) $(STXXL_CXX) phonebills.o -o phonebills.bin $(STXXL_LDLIBS) clean: rm -f phonebills.bin phonebills.o \end{verbatim} Do not forget to configure you external memory space in file {\tt .stxxl}. You can copy the {\tt config\_example} (Windows: {\tt config\_example\_win}) from the \stxxl installation directory, and adapt it to your configuration. % The sources of the billing program as well as input log generation % program are available from \ldots. % running times \chapter{Design of \stxxl} \stxxl is a layered library. There are three layers (see Fig.~\ref{stxxlstructure}). The lowest layer, \emph{Asynchronous I/O primitives layer} hides the details of how I/Os are done. In particular, the layer provides abstraction for \emph{asynchronous} read and write operations on a \emph{file}. The completion status of I/O operations is is facilitated by \emph{I/O request} objects returned by read and write file operations. The layer has several implementations of file access for Linux. The fastest one is based on {\tt read} and {\tt write} system calls which operate directly on user space memory pages\footnote{{\tt O\_DIRECT} option when opening a file.}. To support asynchrony the current Linux implementation of the layer uses standard {\tt pthread} library. Porting \stxxl library to a different platform (for example Windows) involves only reimplementing the Asynchronous I/O primitives layer using native file access methods and/or native multithreading mechanisms\footnote{Porting \stxxl to Windows platform is not finished yet.}. \begin{figure}[hb] \begin{center} \includegraphics[width=8cm]{layer_diagram} \end{center} \vspace*{-0.3cm} \caption{\label{stxxlstructure}The \stxxl library structure} \end{figure} The middle layer, \emph{Block management layer} provides a programming interface simulating the \emph{parallel} disk model. The layer provides abstraction for a fundamental concept in the external memory algorithm design -- block of elements. Block manager implements block allocation/deallocation allowing several block-to-disk assignment strategies: striping, randomized striping, randomized cycling, etc. The block management layer provides implementation of \emph{parallel} disk buffered writing and optimal prefetching \cite{HutSanVit01b}, and block caching. The implementations are fully asynchronous and designed to explicitly support overlapping of I/O and computation. The top of \stxxl consists of two modules (see Fig.~\ref{stxxlstructure}). STL-user layer implements the functionality and interfaces of the STL library. The layer provides external memory sorting, external memory stack, external memory priority queue, etc. which have (almost) the same interfaces (including syntax and semantics) as their STL counterparts. The \emph{Streaming layer} provides efficient support for external memory algorithms with mostly \emph{sequential} I/O pattern, i.e.\ scan, sort, merge, etc. A user algorithm, implemented using this module can save many I/Os\footnote{The doubling algorithm for external memory suffix array construction implemented with this module requires only $1/3$ of I/Os which must be performed by an implementation that uses conventional data structures and algorithms (from \stxxl STL-user layer, or LEDA-SM, or TPIE).}. The win is due to an efficient interface, that couples the input and the output of the algorithms-components (scans, sorts, etc.). The output from an algorithm is directly fed into another algorithm as the input, without the need to store it on the disk. \chapter{STL-User Layer} \stxxl library was designed to ease the access to external memory algorithms and data structures for a programmer. We decided to equip our implementations of \emph{out-of-memory} data structure and algorithms with well known generic interfaces of \emph{internal memory} data structures and algorithms from the Standard Template Library. Currently we have implementation of the following data structures (in STL terminology \emph{containers}): \texttt{vector}, \texttt{stack}, \texttt{priority\_queue}. We have implemented a \emph{parallel} disk sorter which have syntax of STL \texttt{sort} \cite{DemSan03}. Our \texttt{ksort} is a specialized implementation of \texttt{sort} which efficiently sorts elements with integer keys\footnote{\texttt{ksort} is not STL compatible, it extends the syntax of STL.}. \stxxl currently provides several implementations of scanning algorithms (\texttt{generate}, \texttt{for\_each}, \texttt{find}) optimized for external memory. However, it is possible (with some constant factor degradation in the performance) to apply internal memory scanning algorithms from STL to \stxxl containers, since \stxxl containers have iterator based interface. \stxxl has a restriction that the data types stored in the containers can not have pointers or references to other elements of external memory containers. The reason is that those pointers/references get invalidated when the blocks containing the elements they point/refer to are written on the disks. \newcommand{\xvector}{\texttt{stxxl::vector}} \section{Vector} External memory vector (array) \xvector\ is a data structure that supports random access to elements. The semantics of the basic methods of \xvector\ is kept to compatible with STL \texttt{std::vector}. Table~\ref{rtvector} shows the internal work and the I/O worst case complexity of the \xvector. \begin{table} \begin{center} \caption{Running times of the basic operations of \xvector} \label{rtvector} \begin{tabular}{|l|c|c|} \hline & int. work & I/O (worst case) \\ \hline\hline random access & $\Oh{1}$ & $\Oh{1}$\\ \hline insertion at the end& $\Oh{1}$ & $\Oh{1}$\\ \hline removal at the end & $\Oh{1}$ & $\Oh{1}$ \\ \hline \end{tabular} \end{center} \end{table} \subsection{The Architecture of \xvector} The \xvector\ is organized as a collection of blocks residing on the external storage media (parallel disks). Access to the external blocks is organized through the fully associative \emph{cache} which consist of some fixed amount of in-memory pages\footnote{The page is a collection of consecutive blocks. The number of blocks in the page is constant.}. The schema of \xvector\ is depicted in the Fig.~\ref{xvectorschema}. When accessing an element the implementation of \xvector\ access methods (\texttt{[$\cdot$]}~operator, \texttt{push\_back}, etc.) first checks whether the page to which the requested element belongs is in the vector's cache. If it is the case the reference to the element in the cache is returned. Otherwise the page is brought into the cache\footnote{If the page of the element has not been touched so far, this step is skipped. To keep an eye on such situations there is a special flag for each page.}. If there was no free space in the cache, then some page is to be written out. Vector maintains a \emph{pager} object, that tells which page to kick out. \stxxl provides LRU and random paging strategies. The most efficient and default one is LRU. For each page vector maintains the \emph{dirty} flag, which is set when \emph{non-constant} reference to one of the page's elements was returned. The dirty flag is cleared each time when the page is read into the cache. The purpose of the flag is to track whether any element of the page is modified and therefore the page needs to be written to the disk(s) when it has to be evicted from the cache. \begin{figure}[hb] \begin{center} \includegraphics[width=11cm]{vector} \end{center} \vspace*{-0.3cm} \caption{\label{xvectorschema} The schema of \xvector\ that consists of ten external memory pages and has a cache with the capacity of four pages. The first cache page is mapped to external page 1, the second page is mapped to external page 8, and the fourth cache page is mapped to page 5. The third page is not assigned to any external memory page. } \end{figure} In the worst case scenario when vector elements are read/written in the random order each access takes $2 \times blocks\_per\_page$ I/Os. The factor \emph{two} shows up here because one has to write the replaced from cache page and read the required one). However the scanning of the array costs about $n/B$ I/Os using constant vector iterators or const reference to the vector\footnote{$n$ is the number of elements to read or write.} (read-only access). Using non-const vector access methods leads to $2 \times n/B$ I/Os because every page becomes dirty when returning a non const reference. If one needs only to sequentially write elements to the vector in $n/B$ I/Os the currently fastest method is \texttt{stxxl::generate} (see section \ref{stxxl::generate}). Sequential writing to an untouched before vector\footnote{For example writing in the vector that has been created using \texttt{vector(size\_type n)} constructor.} or alone adding elements at the end of the vector\footnote{Using \texttt{void push\_back(const T\&)} method.} leads also to $n/B$ I/Os. {\bf Example of use} \begin{lstlisting} stxxl::vector V; V.push_back(3); assert(V.size() == 1 && V.capacity() >= 1 && V[0] == 3); \end{lstlisting} \newcommand{\xvectorg}{\texttt{stxxl::VECTOR\_GENERATOR}} \subsection{\xvectorg} Besides the type of the elements \xvector\ has many other template parameters (block size, number of blocks per page, pager class, etc.). To make the configuration of the vector type easier \stxxl provides special type generator template meta programs for its containers. The program for \xvector\ is called \xvectorg. {\bf Example of use} \begin{lstlisting} typedef stxxl::VECTOR_GENERATOR::result vector_type; vector_type V; V.push_back(3); assert(V.size() == 1 && V.capacity() >= 1 && V[0] == 3); \end{lstlisting} \begin{table}[h] \begin{center} \caption{Template parameters of \xvectorg\ from left to right.} \label{vectorparam} \begin{tabular}{|l|p{3.5cm}|c|c|} \hline parameter& description & default value & recommended value \\ \hline\hline Tp\_ & element type & & \\ \hline PgSz\_ & number of blocks in a page & 4 & $\geq D$\\ \hline Pages\_ & number of pages in the cache & 8 & $\geq 2$ \\ \hline BlkSize\_ & block size $B$ in bytes & $2\times 1024\times 1024$ & larger is better\\ \hline AllocStr\_ & parallel disk assignment strategy (Table~\ref{allocstr}) & RC & RC \\ \hline Pager\_ & paging strategy (Table~\ref{pagingstr}) & lru & lru \\ \hline \end{tabular} \end{center} \end{table} %%\texttt{stxxl::VECTOR\_GENERATOR< Tp,\\ PgSz,\\ Pages,\\ BlkSize,\\ %%AllocStr,\\ Pager >} \begin{table}[h] \begin{center} \caption{Supported parallel disk assignment strategies.} \label{allocstr} \begin{tabular}{|l|c|} \hline strategy & identifier \\ \hline\hline striping & striping \\ \hline simple randomized & SR\\ \hline fully randomized & FR\\ \hline randomized cycling & RC \\ \hline \end{tabular} \end{center} \end{table} \begin{table}[h] \begin{center} \caption{Supported paging strategies.} \label{pagingstr} \begin{tabular}{|l|c|} \hline strategy & identifier \\ \hline\hline random & random \\ \hline least recently used & lru\\ \hline \end{tabular} \end{center} \end{table} Notes: \begin{itemize} \item All blocks of a page are read and written from/to disks together. Therefore to increase the I/O bandwidth, it is recommended to set the PgSz\_ parameter to multiple of $D$. \end{itemize} Since there are defaults for the last five of the parameters, it is not necessary to specify them all. {\bf Examples:} \begin{itemize} \item \texttt{VECTOR\_GENERATOR::result} -- external vector of {\bf double}'s with four blocks per page, the cache with eight pages, 2~MiB blocks, Random Allocation and lru cache replacement strategy \item \texttt{VECTOR\_GENERATOR::result} -- external vector of {\bf double}'s , with {\bf eight} blocks per page, the cache with eight pages, 2~MiB blocks, Random Allocation and lru cache replacement strategy \item \texttt{VECTOR\_GENERATOR::result} -- external vector of {\bf double}'s, with {\bf eight} blocks per page, the cache with {\bf two} pages, {\bf 512~KiB} blocks, {\bf Simple Randomized} allocation and lru cache replacement strategy \end{itemize} \subsection{Internal Memory Consumption of \xvector} The cache of \xvector\ largely dominates in its internal memory consumption. Other members consume very small fraction of \xvector s memory even when the vector size is large. Therefore, the internal memory consumption of \xvector\ can be estimated as $BlkSize\_ \times Pages\_ \times PgSz\_$ bytes. \subsection{Members of \xvector} See Tables \ref{vectormembers1} and \ref{vectormembers2}. \begin{table}[h] \begin{center} \caption{Members of \xvector. Part 1.} \label{vectormembers1} \begin{tabular}{|p{6cm}|p{5cm}|} \hline member & description \\ \hline\hline \texttt{value\_type} & The type of object, Tp\_, stored in the vector. \\ \hline \texttt{pointer} & Pointer to Tp\_. \\ \hline \texttt{reference} & Reference to Tp\_. \\ \hline \texttt{const\_reference} & Const reference to Tp\_. \\ \hline \texttt{size\_type} & An unsigned 64-bit\footnote{\texttt{off\_t} type. It has the length 64 bits if \ldots} integral type. \\ \hline \texttt{iterator} & Iterator used to iterate through a vector. See notes a,b. \\ \hline \texttt{const\_iterator} & Const iterator used to iterate through a vector. See notes a,b. \\ \hline \texttt{block\_type} & type of the block used in disk-memory transfers \\ \hline \texttt{iterator begin()} & Returns an iterator pointing to the beginning of the vector. See notes a,b. \\ \hline \texttt{iterator end()} & Returns an iterator pointing to the end of the vector. See notes a,b.\\ \hline \texttt{const\_iterator begin() const} & Returns a const\_iterator pointing to the beginning of the vector. See notes a,b.\\ \hline \texttt{const\_iterator end() const} & Returns a const\_iterator pointing to the end of the vector. See notes a,b. \\ \hline \texttt{size\_type size() const} & Returns the size of the vector. \\ \hline \texttt{size\_type capacity() const} & Number of elements for which \emph{external} memory has been allocated. \texttt{capacity()} is always greater than or equal to \texttt{size()}. \\ \hline \texttt{bool empty() const} & true if the vector's size is 0.\\ \hline \texttt{reference operator[](size\_type n)} & Returns (the reference to) the n'th element. See note c.\\ \hline \texttt{const\_reference operator[](size\_type n) const} & Returns (the const reference to) the n'th element. See note c.\\ \hline \end{tabular} \end{center} \end{table} \begin{table}[h] \begin{center} \caption{Members of \xvector. Part 2.} \label{vectormembers2} \begin{tabular}{|p{6cm}|p{5cm}|} \hline member & description \\ \hline\hline \texttt{vector()} & Creates an empty vector. \\ \hline \texttt{vector(size\_type n)} & Creates a vector with n elements. \\ \hline \texttt{vector(const vector\&)} & Not yet implemented \\ \hline \texttt{\textasciitilde vector()} & The destructor. \\ \hline \texttt{void reserve(size\_type n)} & If n is less than or equal to \texttt{capacity()}, this call has no effect. Otherwise, it is a request for allocation of additional \emph{external} memory. If the request is successful, then \texttt{capacity()} is greater than or equal to n; otherwise, \texttt{capacity()} is unchanged. In either case, \texttt{size()} is unchanged. \\ \hline \texttt{reference front()} & Returns (the reference to) the first element. See note c.\\ \hline \texttt{const\_reference front() const} & Returns (the const reference to) the first element. See note c.\\ \hline \texttt{reference back()} & Returns (the reference to) the last element. See note c.\\ \hline \texttt{const\_reference back() const} & Returns (the const reference to) the last element. See note c.\\ \hline \texttt{void push\_back(const T\&)} & Inserts a new element at the end. \\ \hline \texttt{void pop\_back()} & Removes the last element. \\ \hline \texttt{void clear()} & Erases all of the elements and deallocates all external memory that vector occupied.\\ \hline \texttt{void flush()} & Flushes the cache pages to the external memory. \\ \hline \texttt{vector (file * from)} & Create the vector from the file. The construction causes no I/O.\\ \hline \end{tabular} \end{center} \end{table} Notes: \begin{enumerate} \item In opposite to STL, \xvector 's iterators do not get invalidated when the vector is resized or reallocated. \item Dereferencing a non-const iterator makes the page of the element to which the iterator points to \emph{dirty}. This causes the page to be written back to the disks(s) when the page is to be kicked off from the cache (additional write I/Os). If you do not want this behavior, use const iterators instead. Example: \begin{lstlisting} vector_type V; // ... fill the vector here vector_type::iterator iter = V.begin(); // ... advance the iterator a = *iter; // causes write I/Os, // although *iter is not changed vector_type::const_iterator citer = V.begin(); // ... advance the iterator a = *citer; // read-only access, causes no write I/Os *citer = b; // does not compile, citer is const \end{lstlisting} \item Non const \texttt{[$\cdot$]} operator makes the page of the element \emph{dirty}. This causes the page to be written back to the disks(s) when the page is to be kicked off from the cache (additional write I/Os). If you do not want this behavior, use const \texttt{[$\cdot$]} operator. For that you need to access the vector via a const reference to it. Example: \begin{lstlisting} vector_type V; // ... fill the vector here a = V[index]; // causes write I/Os, // although V[index] is not changed const vector_type & CV = V; // const reference to V a = CV[index]; // read-only access, can cause no write I/Os CV[index] = b; // does not compile, CV is const \end{lstlisting} This issue also concerns \texttt{front()} and \texttt{back()} methods. \end{enumerate} \newcommand{\xstack}{\texttt{stxxl::stack}} \section{Stacks} \label{stacksection} Stacks provide only restricted subset of sequence operations: insertion, removal, and inspection of the element at the top of the stack. Stacks are a "last in first out" (LIFO) data structures: the element at the top of a stack is the one that was most recently added. Stacks does not allow iteration through its elements. The \emph{I/O efficient} stack is perhaps the simplest external memory data structure. The basic variant of EM stack keeps the top $k$ elements in the main memory buffer, where $k \leq 2B$. If the buffers get empty on a removal call, one block is brought from the disk to the buffers. Therefore at least $B$ removals are required to make one I/O reading a block. Insertions cause no I/Os until the internal buffers get full. In this case to make space the first $B$ elements are written to the disk. Thus a block write happens only after at least $B$ insertions. If we choose the unit of disk transfer to be a multiple of $DB$ (we denote it as a \emph{page}), set the stack buffer size to $2D$ pages, and evenly assign the blocks of a page to disks we obtain the running times shown in Table~\ref{rtstack}. \begin{table}[h] \begin{center} \caption{Amortized running times of the basic operations of \xstack} \label{rtstack} \begin{tabular}{|l|c|c|} \hline & int. work & I/O (amortized)\\ \hline\hline insertion at the end& $\Oh{1}$ & $\Oh{1/DB}$\\ \hline removal at the end & $\Oh{1}$ & $\Oh{1/DB}$ \\ \hline \end{tabular} \end{center} \end{table} \stxxl has several implementations of the external memory stack. Each implementation is specialized for a certain access pattern: \begin{itemize} \item The {\bf Normal } stack (\texttt{stxxl::normal\_stack}) is a general purpose implementation which is the best if the access pattern to the stack is an irregular mix of push'es and pop's, i.e.\ the stack grows and shrinks without a certain rule. \item The {\bf Grow-Shrink} stack is a stack that is optimized for an access pattern where the insertions are (almost) not intermixed with the removals, and/or vice versa, the removals are (almost) not intermixed with the insertions. In other words the stack first grows to its maximal size, then it shrinks, then it might again grow, then shrink, and so forth, i.e.\ the pattern is $(push^{i_j}pop^{r_j})^k$, where $k \in N$, $1\leq j\leq k$, and $i_j$, $r_j$ are \emph{large}. \item The {\bf Grow-Shrink2} stack is a ``grow-shrink'' stack that allows the use of common prefetch and write buffer pools. The pools are shared between several ``grow-shrink'' stacks. \item The {\bf Migrating} stack is a stack that migrates from internal memory to external when its size exceeds a certain threshold. % todo: describe the optimization in its section later \end{itemize} \newcommand{\xnormalstack}{\texttt{stxxl::normal\_stack}} \subsection{\xnormalstack} The \xnormalstack is a general purpose implementation of the external memory stack. The stack has two pages, the size of the page in blocks is a configuration constant and can be given as a template parameter. The implementation of the methods follows the description given in Section~\ref{stacksection}. \subsection*{Internal Memory Consumption of \xnormalstack} The cache of \xnormalstack\ largely dominates in its internal memory consumption. Other members consume very small fraction of \xnormalstack s memory even when the stack size is large. Therefore, the internal memory consumption of \xnormalstack\ can be estimated as $2 \times BlkSize\_ \times PgSz\_$ bytes, where $BlkSize\_$ is the block size and $PgSz\_$ is the page size in blocks (see Section~\ref{stackgensection}). \subsection*{Members of \xnormalstack} See Table~\ref{normalstackmembers}. \begin{table}[h] \begin{center} \caption{Members of \xnormalstack.} \label{normalstackmembers} \begin{tabular}{|p{6cm}|p{5cm}|} \hline member & description \\ \hline\hline \texttt{value\_type} & The type of object, Tp\_, stored in the vector. \\ \hline \texttt{size\_type} & An unsigned 64-bit\footnote{\texttt{off\_t} type. It has the length 64 bits if \ldots} integral type. \\ \hline \texttt{block\_type} & type of the block used in disk-memory transfers \\ \hline \texttt{bool empty() const} & Returns true if the stack contains no elements, and false otherwise. \texttt{S.empty()} is equivalent to \texttt{S.size() == 0}. \\ \hline \texttt{size\_type size() const} & Returns the number of elements contained in the stack. \\ \hline \texttt{value\_type\& top()} & Returns a mutable reference to the element at the top of the stack. Precondition: \texttt{empty()} is false. \\ \hline \texttt{const value\_type\& top() const} & Returns a const reference to the element at the top of the stack. Precondition: \texttt{empty()} is false.\\ \hline \texttt{void push(const value\_type\& x)} & Inserts x at the top of the stack. Postconditions: \texttt{size()} will be incremented by 1, and \texttt{top()} will be equal to x. \\ \hline \texttt{void pop()} & Removes the element at the top of the stack. Precondition: \texttt{empty()} is false. Postcondition: size() will be decremented by 1. \\ \hline \texttt{normal\_stack()} & he default constructor. Creates an empty stack.\\ \hline \texttt{template normal\_stack(const stack\_type \& stack\_)} & The copy constructor. Accepts any \emph{stack concept} data type.\\ \hline \texttt{\textasciitilde normal\_stack()} & The destructor.\\ \hline \end{tabular} \end{center} \end{table} The running times of the push/pop stack operations are given in Table~\ref{rtstack}. Other operations except copy construction perform constant internal work and no I/Os. \newcommand{\xgsstack}{\texttt{stxxl::grow\_shrink\_stack}} \subsection{\xgsstack} The \xgsstack\ stack specialization is optimized for an access pattern where the insertions are (almost) not intermixed with the removals, and/or vice versa, the removals are (almost) not intermixed with the insertions. In other words the stack first grows to its maximal size, then it shrinks, then it might again grow, then shrink, and so forth, i.e.\ the pattern is $(push^{i_j}pop^{r_j})^k$, where $k \in N$, $1\leq j\leq k$, and $i_j$, $r_j$ are \emph{large}. The implementation efficiently exploits the knowledge of the access pattern that allows \emph{prefetching} the blocks beforehand while the stack shrinks and \emph{buffered writing} while the stack grows. Therefore the \emph{overlapping} of I/O and computation is possible. \subsection*{Internal Memory Consumption of \xgsstack} The cache of \xgsstack\ largely dominates in its internal memory consumption. Other members consume very small fraction of \xgsstack 's memory even when the stack size is large. Therefore, the internal memory consumption of \xgsstack\ can be estimated as $2 \times BlkSize\_ \times PgSz\_$ bytes, where $BlkSize\_$ is the block size and $PgSz\_$ is the page size in blocks (see Section~\ref{stackgensection}). \subsection*{Members of \xgsstack} The \xgsstack has the same set of members as the \xnormalstack\ (see Table~\ref{normalstackmembers}). The running times of \xgsstack\ are the same as \xnormalstack\ except that when the stack switches from growing to shrinking (or from shrinking to growing) $PgSz\_$ I/Os can be spent additionally in the worst case.\footnote{This is for the single disk setting, if the page is perfectly striped over parallel disk the number of I/Os is $PgSz\_/D$.} \newcommand{\xgsstacktwo}{\texttt{stxxl::grow\_shrink\_stack2}} \subsection{\xgsstacktwo} The \xgsstacktwo\ is optimized for the same kind of access pattern as \xgsstack. The difference is that each instance of \xgsstack\ uses an own internal buffer to overlap I/Os and computation, but \xgsstacktwo\ is able to share the buffers from the pool used by several stacks. % mention the documentation of prefetch\_pool and write\_pool. \subsection*{Internal Memory Consumption of \xgsstacktwo} Not counting the memory consumption of the shared blocks from the pools, the stack alone consumes about $BlkSize\_$ bytes.\footnote{It has the cache that consists of only a single block.} \subsection*{Members of \xgsstacktwo} The \xgsstacktwo\ has almost the same set of members as the \xnormalstack\ (Table~\ref{normalstackmembers}), except that it does not have the default constructor. The \xgsstacktwo\ requires prefetch and write pool objects (see Sections \ref{prefetchpoolsection} and \ref{writepoolsection} for the documentation for the pool classes) to be specified in the creation time. The new members are listed in Table~\ref{gsstacktwomembers}. \begin{table}[h] \begin{center} \caption{New members of \xgsstacktwo.} \label{gsstacktwomembers} \begin{tabular}{|p{6cm}|p{5cm}|} \hline member & description \\ \hline\hline \texttt{grow\_shrink\_stack2 (prefetch\_pool< block\_type > \& p\_pool\_, write\_pool< block\_type > \&w\_pool\_, unsigned prefetch\_aggressiveness=0)} & Constructs stack, that will use \texttt{p\_pool\_} for prefetching and \texttt{w\_pool\_} for buffered writing. \texttt{prefetch\_aggressiveness} parameter tells how many blocks from the prefetch pool the stack is allowed to use.\\ \hline \texttt{void set\_prefetch\_aggr (unsigned new\_p)} & Sets level of prefetch aggressiveness (number of blocks from the prefetch pool used for prefetching). \\ \hline \texttt{unsigned get\_prefetch\_aggr () const} & Returns the number of blocks used for prefetching. \\ \hline \end{tabular} \end{center} \end{table} \newcommand{\xmstack}{\texttt{stxxl::migrating\_stack}} \subsection{\xmstack} The \xmstack\ is a stack that migrates from internal memory to external when its size exceeds a certain threshold (template parameter). The implementation of internal and external memory stacks can be arbitrary and given as a template parameters. \subsection*{Internal Memory Consumption of \xmstack} The \xmstack\ memory consumption depends on the memory consumption of the stack implementations given as template parameters. The the current state is internal (external), the \xmstack\ consumes almost exactly the same space as internal (external) memory stack implementation.\footnote{The \xmstack\ needs only few pointers to maintain the switching from internal to external memory implementations.} \subsection*{Members of \xmstack} The \xmstack\ extends the member set of \xnormalstack\ (Table~\ref{normalstackmembers}). The new members are listed in Table~\ref{migratingstackmembers}. \begin{table}[h] \begin{center} \caption{New members of \xmstack.} \label{migratingstackmembers} \begin{tabular}{|p{6cm}|p{5cm}|} \hline member & description \\ \hline\hline \texttt{bool internal () const} & Returns true if the current implementation is internal, otherwise false. \\ \hline \texttt{bool external () const} & Returns true if the current implementation is external, otherwise false. \\ \hline \end{tabular} \end{center} \end{table} \newcommand{\xstackg}{\texttt{stxxl::STACK\_GENERATOR}} \subsection{\xstackg} \label{stackgensection} To provide an easy way to choose and configure the \xstack\ implementations \stxxl offers a template meta program called \xstackg. See Table~\ref{stackparam}. {\bf Example:} \begin{lstlisting} typedef stxxl::STACK_GENERATOR::result stack_type; int main() { stack_type S; S.push(8); S.push(7); S.push(4); assert(S.size() == 3); assert(S.top() == 4); S.pop(); assert(S.top() == 7); S.pop(); assert(S.top() == 8); S.pop(); assert(S.empty()); } \end{lstlisting} \begin{table}[h] \begin{center} \caption{Template parameters of \xstackg\ from left to right.} \label{stackparam} \begin{tabular}{|l|p{4.5cm}|c|c|} \hline parameter& description & default value & recommended value \\ \hline\hline ValTp & element type & & \\ \hline Externality & tells whether the vector is internal, external, or migrating (Table~\ref{externality}) & external & \\ \hline Behavior & chooses \emph{external} implementation (Table~\ref{behaviour})& normal & \\ \hline BlocksPerPage & defines how many blocks has one page of internal cache of an \emph{external} implementation & 4 & $\geq D$ \\ \hline BlkSz & external block size in bytes & $2\times 1024\times 1024$ & larger is better\\ \hline IntStackTp & type of internal stack (used for the migrating stack) & \texttt{std::stack} &\\ \hline MigrCritSize & threshold value for number of elements when \texttt{migrating\_stack} migrates to the external memory & $2\times BlocksPerPage\times BlkSz$ & \\ \hline AllocStr & parallel disk assignment strategy (Table~\ref{allocstr}) & RC & RC \\ \hline SzTp & size type & \texttt{off\_t} & \texttt{off\_t} \\ \hline \end{tabular} \end{center} \end{table} \begin{table}[h] \begin{center} \caption{The Externality parameter.} \label{externality} \begin{tabular}{|l|p{7cm}|} \hline identifier & comment \\ \hline\hline internal & chooses IntStackTp implementation\\ \hline external & external container, implementation is chosen according to the Behavior parameter\\ \hline migrating & migrates from internal implementation given by IntStackTp parameter to external implementation given by Behavior parameter when size exceeds MigrCritSize \\ \hline \end{tabular} \end{center} \end{table} \begin{table}[h] \begin{center} \caption{The Behavior parameter.} \label{behaviour} \begin{tabular}{|l|p{7cm}|} \hline identifier & comment \\ \hline\hline normal & conservative version, implemented in \xnormalstack \\ \hline grow\_shrink & chooses \xgsstack \\ \hline grow\_shrink2 & chooses \xgsstacktwo \\ \hline \end{tabular} \end{center} \end{table} {\bf Example for \xgsstacktwo\ :} \begin{lstlisting} typedef STACK_GENERATOR::result stack_type; typedef stack_type::block_type block_type; stxxl::prefetch_pool p_pool(10); // 10 read buffers stxxl::write_pool w_pool(6); // 6 write buffers stack_type S(p_pool,w_pool,0); // no read buffers used for(long long i=0;i < max_value;++i) S.push(i); S.set_prefetch_aggressiveness(5); /* give a hint that we are going to shrink the stack from now on, always prefetch 5 buffers beforehand */ for(long long i=0; i< max_value;++i) S.pop(); S.set_prefetch_aggressiveness(0); // stop prefetching \end{lstlisting} \section{Priority Queue} A priority queue is a data structure that provides a restricted subset of container functionality: it provides insertion of elements, and inspection and removal of the top element. It is guaranteed that the top element is the largest element in the priority queue, where the function object \texttt{Cmp\_} is used for comparisons. Priority queue does not allow iteration through its elements. \newcommand{\xpqueue}{\texttt{stxxl::priority\_queue}} \stxxl priority queue is an external memory implementation of \cite{San00b}. The difference to the original design is that the last merge groups keep their sorted sequences in the external memory. The running times of \xpqueue\ data structure is given in Table~\ref{rtpqueue}. The theoretic guarantees on I/O performance are given only for a single disk setting, however the queue also performs well in practice for multi-disk configuration. \begin{table}[h] \begin{center} \caption{Amortized running times of the basic operations of \xpqueue{} in terms of $I =$ the number of performed operations.} \label{rtpqueue} \begin{tabular}{|l|c|c|} \hline & int. work & I/O (amortized)\\ \hline\hline insertion & $\Oh{\log I}$ & $\Oh{1/B}$\\ \hline deletion & $\Oh{\log I}$ & $\Oh{1/B}$ \\ \hline \end{tabular} \end{center} \end{table} \subsection{Members of \xpqueue} See Table~\ref{pqueuemembers}. \begin{table}[h] \begin{center} \caption{Members of \xpqueue.} \label{pqueuemembers} \begin{tabular}{|p{6cm}|p{5cm}|} \hline member & description \\ \hline\hline \texttt{value\_type} & The type of object, Tp\_, stored in the vector. \\ \hline \texttt{size\_type} & An unsigned 64-bit\footnote{\texttt{off\_t} type. It has the length 64 bits if \ldots} integral type. \\ \hline \texttt{block\_type} & type of the block used in disk-memory transfers \\ \hline \texttt{priority\_queue( prefetch\_pool\& p\_pool\_, write\_pool\& w\_pool\_)} & Creates an empty priority queue. Prefetch pool \texttt{p\_pool\_} and write pools \texttt{w\_pool\_} will be used for overlapping of I/O and computation during external memory merging (see Sections \ref{prefetchpoolsection} and \ref{writepoolsection} for the documentation for the pool classes).\\ \hline \texttt{bool empty() const} & Returns true if the \texttt{priority\_queue} contains no elements, and false otherwise. \texttt{S.empty()} is equivalent to \texttt{S.size() == 0}. \\ \hline \texttt{size\_type size() const} & Returns the number of elements contained in the \texttt{priority\_queue}. \\ \hline \texttt{const value\_type\& top() const} & Returns a const reference to the element at the top of the \texttt{priority\_queue}. The element at the top is guaranteed to be the largest element in the priority queue, as determined by the comparison function \texttt{Cmp\_}. That is, for every other element x in the \texttt{priority\_queue}, \texttt{Cmp\_(Q.top(), x)} is false. Precondition: \texttt{empty()} is false. \\ \hline \texttt{void push(const value\_type\& x)}& Inserts x into the \texttt{priority\_queue}. Postcondition: \texttt{size()} will be incremented by 1.\\ \hline \texttt{void pop()} & Removes the element at the top of the \texttt{priority\_queue}, that is, the largest element in the \texttt{priority\_queue}. Precondition: \texttt{empty()} is false. Postcondition: \texttt{size()} will be decremented by 1. \\ \hline \texttt{unsigned mem\_cons () const} & Returns number of bytes consumed by the \texttt{priority\_queue} in the internal memory not including the pools.\\ \hline \texttt{\textasciitilde priority\_queue()} & The destructor. Deallocates all occupied internal and external memory.\\ \hline \end{tabular} \end{center} \end{table} \newcommand{\xpqueueg}{\texttt{stxxl::PRIORITY\_QUEUE\_GENERATOR}} \subsection{\xpqueueg} Since the \xpqueue\ has many setup parameters (internal memory buffer sizes, arity of mergers, number of internal and external memory merger groups, etc.) which are difficult to guess, \stxxl\ provides a helper meta template program that searches for the optimum settings for user demands. The program is called \xpqueueg. The parameter of the program are given in Table~\ref{pqueueparam}. \begin{table}[h] \begin{center} \caption{Template parameters of \xpqueueg\ from left to right.} \label{pqueueparam} \begin{tabular}{|l|p{4.5cm}|c|c|} \hline parameter& description & default value & recommended value \\ \hline\hline Tp\_ & element type & & \\ \hline Cmp\_ & the comparison type used to determine whether one element is smaller than another element. See note a.& & \\ \hline IntM\_ & upper limit for internal memory consumption in bytes & & larges is better\\ \hline MaxS\_ & upper limit for number of elements contained in the priority queue (in units of 1024 items). See note b. & & \\ \hline Tune\_ & a tuning parameter. See note c. & 6 &\\ \hline \end{tabular} \end{center} \end{table} Notes: \begin{enumerate} \item If \texttt{Cmp\_(x,y)} is true, then x is smaller than y. The element returned by \texttt{Q.top()} is the largest element in the priority queue. That is, it has the property that, for every other element x in the priority queue, \texttt{Cmp\_(Q.top(), x)} is false. \texttt{Cmp\_} must also provide \texttt{min\_value} method, that returns value of type \texttt{Tp\_} that is smaller than any element of the queue x , i.e.\ \texttt{Cmp\_(Cmp\_.min\_value(),x))} is always true. Example, a comparison object for priority queue where \texttt{top()} returns the \emph{smallest} contained integer: \begin{lstlisting} struct CmpIntGreater { bool operator () (const int & a, const int & b) { return a::max)(); } }; \end{lstlisting} Example, a comparison object for priority queue where \texttt{top()} returns the \emph{largest} contained integer: \begin{lstlisting} struct CmpIntLess: public std::less { int min_value() const { return (std::numeric_limits::min)(); } }; \end{lstlisting} Note that \texttt{Cmp\_} must define the Strict Weak Ordering. \item Example: if you are sure that priority queue contains no more than one million elements any time, then the right parameter for you is $(1000000/1024)= 976$. \item Try to play with the Tune\_ parameter if the your code does not compile (larger than default value 6 might help). The reason that the code does not compile is that no suitable internal parameters were found for given IntM\_ and MaxS\_. It might also happen that given IntM\_ is too small for given MaxS\_, try larger values. \texttt{PRIORITY\_QUEUE\_GENERATOR} searches for 7 configuration parameters of \xpqueue\ that both minimize internal memory consumption of the priority queue to match IntM\_ and maximize the performance of priority queue operations. Actual memory consumption might be slightly larger (use \texttt{stxxl::priority\_queue::mem\_cons()} method to track it), since the search assumes rather optimistic schedule of push'es and pop'es for the estimation of the maximum memory consumption. To keep actual memory requirements low, increase the value of MaxS\_ parameter. \item For the functioning, a priority queue object requires two pools of blocks (See the constructor of \texttt{priority\_queue} ). To construct \stxxl block pools you need the block type that is used by priority queue. Block's size and hence it's type is generated by the \texttt{PRIORITY\_QUEUE\_GENERATOR} in compile type from IntM\_, MaxS\_ and \texttt{sizeof(Tp\_)} and it can not be given directly by the user as a template parameter. The block type can be accessed as\\ \texttt{PRIORITY\_QUEUE\_GENERATOR::result::block\_type}. \end{enumerate} {\bf Example:} \begin{lstlisting} struct Cmp { bool operator () (const int & a, const int & b) const { return a>b; } int min_value() const { return (std::numeric_limits::max)(); } }; typedef stxxl::PRIORITY_QUEUE_GENERATOR::result pq_type; typedef pq_type::block_type block_type; int main() { // use 10 block read and write pools // for enable overlapping of I/O and // computation stxxl::prefetch_pool p_pool(10); stxxl::write_pool w_pool(10); pq_type Q(p_pool,w_pool); Q.push(1); Q.push(4); Q.push(2); Q.push(8); Q.push(5); Q.push(7); assert(Q.size() == 6); assert(Q.top() == 8); Q.pop(); assert(Q.top() == 7); Q.pop(); assert(Q.top() == 5); Q.pop(); assert(Q.top() == 4); Q.pop(); assert(Q.top() == 2); Q.pop(); assert(Q.top() == 1); Q.pop(); assert(Q.empty()); } \end{lstlisting} \subsection{Internal Memory Consumption of \xpqueue} Internal memory consumption of \xpqueue\ is bounded by the IntM\_ parameter in most situations. \newcommand{\xsort}{{\texttt{stxxl::sort}}} \newcommand{\xksort}{{\texttt{stxxl::ksort}}} \newcommand{\stdsort}{{\texttt{std::sort}}} \section{\stxxl Algorithms} Iterators of \xvector\ are STL compatible. \texttt{stxxl::vector::iterator} is a model of Random Access Iterator concept from STL. Therefore it is possible to use the \xvector\ iterator ranges with STL algorithms. However such use is not I/O efficient if an algorithm accesses the sequence in a random order. For such kind of algorithms \stxxl provides I/O efficient implementations described in this chapter (Sections~\ref{sortsection}--\ref{ksortsection}). If an algorithm does only a scan (or a constant number of scans) of a sequence (or sequences) the implementation that calls STL algorithm is nevertheless I/O efficient. However one can save constant factors in I/O volume and internal work if the the access pattern is known (read-only or write-only scan for example). This knowledge is used in \stxxl specialized implementations of STL algorithms (Section~\ref{otheralgs}). \subsection*{Example: STL Algorithms Running on \stxxl containers} \begin{lstlisting} typedef stxxl::VECTOR_GENERATOR::result vector_type; // Replace every number in an array with its negative. const int N = 1000000000; vector_type A(N); std::iota(A.begin(), A.end(), 1); std::transform(A, A+N, A, negate()); // Calculate the sum of two vectors, // storing the result in a third vector. const int N = 1000000000; vector_type V1(N); vector_type V2(N); vector_type V3(N); std::iota(V1.begin(), V1.end(), 1); std::fill(V2.begin(), V2.end(), 75); assert(V2.size() >= V1.size() && V3.size() >= V1.size()); std::transform(V1.begin(), V1.end(), V2.begin(), V3.begin(), plus()); \end{lstlisting} \section{Sorting} \label{sortsection} \xsort\ is an external memory equivalent to STL \stdsort. The design and implementation of the algorithm is described in detail in \cite{DemSan03}. \subsection*{Prototype} \begin{lstlisting} template < typename ExtIterator_, typename StrictWeakOrdering_ > void sort ( ExtIterator_ first, ExtIterator_ last, StrictWeakOrdering_ cmp, unsigned M ) \end{lstlisting} \subsection*{Description} \xsort\ sorts the elements in [first, last) into ascending order, meaning that if \texttt{i} and \texttt{j} are any two valid iterators in [first, last) such that \texttt{i} precedes \texttt{j}, then \texttt{*j} is not less than \texttt{*i}. Note: as \stdsort, \xsort\ is not guaranteed to be stable. That is, suppose that \texttt{*i} and \texttt{*j} are equivalent: neither one is less than the other. It is not guaranteed that the relative order of these two elements will be preserved by \xsort. The order is defined by the \texttt{cmp} parameter. The sorter's internal memory consumption is bounded by \texttt{M} bytes. \subsection*{Requirements on Types} \begin{itemize} \item \texttt{ExtIterator\_} is a model of External Random Access Iterator\footnote{In \stxxl currently only \xvector\ provides iterators that are models of External Random Access Iterator.}. \item \texttt{ExtIterator\_} is mutable. \item \texttt{StrictWeakOrdering\_} is a model of Strict Weak Ordering and must provide min and max values for the elements in the input: \begin{itemize} \item \texttt{max\_value} method that returns an object that is \emph{strictly greater} than all other objects of user type according to the given ordering. \item \texttt{min\_value} method that returns an object that is \emph{strictly less} than all other objects of user type according to the given ordering. \end{itemize} {\bf Example:} a comparison object for ordering integer elements in the ascending order \begin{lstlisting} struct CmpIntLess: public std::less { static int min_value() const { return (std::numeric_limits::min)(); } static int max_value() const { return (std::numeric_limits::max)(); } }; \end{lstlisting} {\bf Example:} a comparison object for ordering integer elements in the descending order \begin{lstlisting} struct CmpIntGreater: public std::greater { int min_value() const { return (std::numeric_limits::max)(); } int max_value() const { return (std::numeric_limits::min)(); } }; \end{lstlisting} Note, that according to the \xsort\ requirements \texttt{min\_value} and \texttt{max\_value} {\bf can not} be present in the input sequence. \item \texttt{ExtIterator\_}'s value type is convertible to \texttt{StrictWeakOrdering\_}'s argument type. \end{itemize} \subsection*{Preconditions} \label{sortpreconditions} [first, last) is a valid range. \subsection*{Complexity} \label{sortcomplexity} \begin{itemize} \item Internal work: $\Oh{N \log N}$, where \\$N = (last - first)\cdot$~\texttt{sizeof(ExtIterator\_::value\_type)}. \item I/O complexity: $(2N/DB)(1 + \lceil {\log}_{M/B}(2N/M) \rceil)$ I/Os \end{itemize} \xsort\ chooses the block size (parameter $B$) equal to the block size of the container, the last and first iterators pointing to (e.g.\ \xvector's block size). The second term in the I/O complexity accounts for the merge phases of the external memory sorting algorithm \cite{DemSan03}. Avoiding multiple merge phases speeds up the sorting. In practice one should choose the block size $B$ of the container to be sorted such that there is only one merge phase needed: $\lceil {\log}_{M/B}(2N/M) \rceil) = 1$. This is possible for $M > DB$ and $N < M^2/2DB$. But still this restriction gives a freedom to choose a variety of blocks sizes. The study \cite{DemSan03} has shown that optimal $B$ for sorting lies in the range $[M^2/(4N),3M^2/(8N)]$. With such choice of the parameters the \xsort\ always performs $4N/DB$ I/Os. \subsection*{Internal Memory Consumption} \label{sortimem} The \xsort\ consumes slightly more than \emph{M} bytes of internal memory. \subsection*{External Memory Consumption} \label{sortemem} The \xsort\ is not in-place. It requires about $N$ bytes of external memory to store the sorted runs during the sorting process \cite{DemSan03}. After the sorting this memory is freed. \subsection*{Example} \begin{lstlisting} struct MyCmp: public std::less // ascending { // order static int min_value() const { return (std::numeric_limits::min)(); } static int max_value() const { return (std::numeric_limits::max)(); } }; typedef stxxl::VECTOR_GENERATOR::result vec_type; vec_type V; // ... fill here the vector with some values /* Sort in ascending order use 512 MiB of main memory */ stxxl::sort(V.begin(),V.end(),MyCmp(),512*1024*1024); // sorted \end{lstlisting} \section{Sorted Order Checking} \stxxl gives an ability to automatically check the order in the output of \stxxl \footnote{This checker checks the \xsort, \xksort\ (Section~\ref{ksortsection}), and the pipelined sorter from Section~\ref{pipesorting}.} sorters and intermediate results of sorting (the order and a meta information in the sorted runs). The check is switched on if the source codes and the library are compiled with the option \texttt{-DSTXXL\_CHECK\_ORDER\_IN\_SORTS} and the option \texttt{-DNDEBUG} is not used. For details see the \texttt{compiler.make} file in the \stxxl tar ball. Note, that the checking routines require more internal work as well as additional $N/DB$ I/Os to read the sorted runs. Therefore for the final non-debug version of a user application on should switch this option off. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \section{Sorting Using Integer Keys} \label{ksortsection} \xksort\ is a specialization of external memory sorting optimized for records having integer keys. \subsection*{Prototype} \begin{lstlisting} template < typename ExtIterator_> void ksort ( ExtIterator_ first, ExtIterator_ last, unsigned M ) template < typename ExtIterator_, typename KeyExtractor_> void ksort ( ExtIterator_ first, ExtIterator_ last, KeyExtractor_ keyobj, unsigned M ) \end{lstlisting} \subsection*{Description} \xksort\ sorts the elements in [first, last) into ascending order, meaning that if \texttt{i} and \texttt{j} are any two valid iterators in [first, last) such that \texttt{i} precedes \texttt{j}, then \texttt{*j} is not less than \texttt{*i}. Note: as \stdsort and \xsort, \xksort\ is not guaranteed to be stable. That is, suppose that \texttt{*i} and \texttt{*j} are equivalent: neither one is less than the other. It is not guaranteed that the relative order of these two elements will be preserved by \xksort. The two versions of \xksort\ differ in how they define whether one element is less than another. The first version assumes that the elements have \texttt{key()} member function that returns an integral key (32 or 64 bit), as well as the minimum and the maximum element values. The second version compares objects extracting the keys using \texttt{keyobj} object, that is in turn provides min and max element values. The sorter's internal memory consumption is bounded by \texttt{M} bytes. \subsection*{Requirements on Types} \begin{itemize} \item \texttt{ExtIterator\_} is a model of External Random Access Iterator\footnote{In \stxxl currently only \xvector\ provides iterators that are models of External Random Access Iterator.}. \item \texttt{ExtIterator\_} is mutable. \item \texttt{KeyExtractor\_} must implement \texttt{operator ()} that extracts the key of an element and provide min and max values for the elements in the input: \begin{itemize} \item \texttt{key\_type} typedef for the type of the keys. \item \texttt{max\_value} method that returns an object that is \emph{strictly greater} than all other keys of the elements in the input. \item \texttt{min\_value} method that returns an object that is \emph{strictly less} than all other keys of the elements in the input. \end{itemize} {\bf Example:} a key extractor object for ordering elements having 64 bit integer keys: \begin{lstlisting} struct MyType { typedef unsigned long long key_type; key_type _key; char _data[32]; MyType() {} MyType(key_type __key):_key(__key) {} }; struct GetKey { typedef MyType::key_type key_type; key_type operator() (const MyType & obj) { return obj._key; } MyType min_value() const { return MyType( (std::numeric_limits::min)()); } MyType max_value() const { return MyType( (std::numeric_limits::max)()); } }; \end{lstlisting} Note, that according to the \xsort\ requirements \texttt{min\_value} and \texttt{max\_value} {\bf can not} be present in the input sequence. \item \texttt{ExtIterator\_}'s value type is convertible to \texttt{KeyExtractor\_}'s argument type. \item \texttt{ExtIterator\_}'s value type has a typedef \texttt{key\_type}. \item For the first version of \xksort\ \texttt{ExtIterator\_}'s value type must have the \texttt{key()} function that returns the key value of the element, and the \texttt{min\_value()} and \texttt{max\_value()} member functions that return minimum and maximum element values respectively. Example: \begin{lstlisting} struct MyType { typedef unsigned long long key_type; key_type _key; char _data[32]; MyType() {} MyType(key_type __key):_key(__key) {} key_type key() { return _key; } MyType min_value() const { return MyType( (std::numeric_limits::min)()); } MyType max_value() const { return MyType( (std::numeric_limits::max)()); } }; \end{lstlisting} \end{itemize} \subsection*{Preconditions} The same as for \xsort\ (section~\ref{sortpreconditions}). \subsection*{Complexity} The same as for \xsort\ (Section~\ref{sortcomplexity}). \subsection*{Internal Memory Consumption} The same as for \xsort\ (Section~\ref{sortimem}) \subsection*{External Memory Consumption} The same as for \xsort\ (Section~\ref{sortemem}). \subsection*{Example} \begin{lstlisting} struct MyType { typedef unsigned long long key_type; key_type _key; char _data[32]; MyType() {} MyType(key_type __key):_key(__key) {} key_type key() { return obj._key; } static MyType min_value() const { return MyType( (std::numeric_limits::min)()); } static MyType max_value() const { return MyType( (std::numeric_limits::max)()); } }; typedef stxxl::VECTOR_GENERATOR::result vec_type; vec_type V; // ... fill here the vector with some values /* Sort in ascending order use 512 MiB of main memory */ stxxl::ksort(V.begin(),V.end(),512*1024*1024); // sorted \end{lstlisting} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \section{Other \stxxl Algorithms} \label{otheralgs} \stxxl offers several specializations of STL algorithms for \xvector\ iterators. The algorithms while accessing the elements bypass the vector's cache and access the vector's blocks directly. Another improvement is that algorithms from this chapter are able to overlap I/O and computation. With standard STL algorithms the overlapping is not possible. This measures save constant factors both in I/O volume and internal work. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%5 \subsection{\texttt{stxxl::generate}} \label{stxxl::generate} The semantics of the algorithm is equivalent to the STL \texttt{std::generate}. \subsection*{Prototype} \begin{lstlisting} template void generate ( ExtIterator first, ExtIterator last, Generator gen, int nbuffers ) \end{lstlisting} \subsection*{Description} Generate assigns the result of invoking \texttt{gen}, a function object that takes no arguments, to each element in the range [first, last). To overlap I/O and computation \texttt{nbuffers} are used (a value at least $D$ is recommended). The size of the buffers is derived from the container that is pointed by the iterators. \subsection*{Requirements on types} \begin{itemize} \item \texttt{ExtIterator} is a model of External Random Access Iterator. \item \texttt{ExtIterator} is mutable. \item \texttt{Generator} is a model of STL Generator. \item \texttt{Generator}'s result type is convertible to \texttt{ExtIterator}'s value type. \end{itemize} \subsection*{Preconditions} [first, last) is a valid range. \subsection*{Complexity} \begin{itemize} \item Internal work is linear. \item External work: close to $N/DB$ I/Os (write-only). \end{itemize} \subsection*{Example} \begin{lstlisting} // Fill a vector with random numbers, using the // standard C library function rand. typedef stxxl::VECTOR_GENERATOR::result vector_type; vector_type V(some_size); // use 20 buffer blocks stxxl::generate(V.begin(), V.end(), rand, 20); \end{lstlisting} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%5 \newcommand{\xforeach}{{\texttt{stxxl::for\_each}}} \subsection{\xforeach} The semantics of the algorithm is equivalent to the STL \texttt{std::for\_each}. \subsection*{Prototype} \begin{lstlisting} template UnaryFunction for_each ( ExtIterator first, ExtIterator last, UnaryFunction f, int nbuffers ) \end{lstlisting} \subsection*{Description} \xforeach\ applies the function object \texttt{f} to each element in the range [first, last); \texttt{f}'s return value, if any, is ignored. Applications are performed in forward order, i.e.\ from first to last. \xforeach\ returns the function object after it has been applied to each element. To overlap I/O and computation \texttt{nbuffers} are used (a value at least $D$ is recommended). The size of the buffers is derived from the container that is pointed by the iterators. \subsection*{Requirements on types} \begin{itemize} \item \texttt{ExtIterator} is a model of External Random Access Iterator. \item \texttt{UnaryFunction} is a model of STL Unary Function. \item \texttt{UnaryFunction} does not apply any non-constant operations through its argument. \item \texttt{ExtIterator}'s value type is convertible to \texttt{UnaryFunction}'s argument type. \end{itemize} \subsection*{Preconditions} [first, last) is a valid range. \subsection*{Complexity} \begin{itemize} \item Internal work is linear. \item External work: close to $N/DB$ I/Os (read-only). \end{itemize} \subsection*{Example} \begin{lstlisting} template struct print : public unary_function { print(ostream& out) : os(out), count(0) {} void operator() (T x) { os << x << ' '; ++count; } ostream& os; int count; }; typedef stxxl::VECTOR_GENERATOR::result vector_type; int main() { vector_type A(N); // fill A with some values // ... print P = stxxl::for_each(A.begin(), A.end(), print(cout)); cout << endl << P.count << " objects printed." << endl; } \end{lstlisting} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \newcommand{\xforeachm}{{\texttt{stxxl::for\_each\_m}}} \subsection{\xforeachm} \xforeachm\ is a \emph{mutating} version of \xforeach, i.e.\ the restriction that Unary Function f can not apply any non-constant operations through its argument does not exist. \subsection*{Prototype} \begin{lstlisting} template UnaryFunction for_each ( ExtIterator first, ExtIterator last, UnaryFunction f, int nbuffers ) \end{lstlisting} \subsection*{Description} \xforeach\ applies the function object \texttt{f} to each element in the range [first, last); \texttt{f}'s return value, if any, is ignored. Applications are performed in forward order, i.e.\ from first to last. \xforeach\ returns the function object after it has been applied to each element. To overlap I/O and computation \texttt{nbuffers} are used (a value at least $2D$ is recommended). The size of the buffers is derived from the container that is pointed by the iterators. \subsection*{Requirements on types} \begin{itemize} \item \texttt{ExtIterator} is a model of External Random Access Iterator. \item \texttt{UnaryFunction} is a model of STL Unary Function. \item \texttt{ExtIterator}'s value type is convertible to \texttt{UnaryFunction}'s argument type. \end{itemize} \subsection*{Preconditions} [first, last) is a valid range. \subsection*{Complexity} \begin{itemize} \item Internal work is linear. \item External work: close to $2N/DB$ I/Os (read and write). \end{itemize} \subsection*{Example} \begin{lstlisting} struct AddX { int x; AddX(int x_): x(x_) {} void operator() (int & val) { val += x; } }; typedef stxxl::VECTOR_GENERATOR::result vector_type; int main() { vector_type A(N); // fill A with some values // ... // Add 5 to each value in the vector stxxl::for_each(A.begin(), A.end(), AddX(5)); } \end{lstlisting} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%5 \subsection{\texttt{stxxl::find}} \label{stxxl::find} The semantics of the algorithm is equivalent to the STL \texttt{std::find}. \subsection*{Prototype} \begin{lstlisting} template< typename ExtIterator, typename EqualityComparable> ExtIterator find ( ExtIterator first, ExtIterator last, const EqualityComparable & value, int nbuffers ) \end{lstlisting} \subsection*{Description} Returns the first iterator \texttt{i} in the range [first, last) such that \texttt{*i == value}. Returns last if no such iterator exists. To overlap I/O and computation \texttt{nbuffers} are used (a value at least $D$ is recommended). The size of the buffers is derived from the container that is pointed by the iterators. \subsection*{Requirements on types} \begin{enumerate} \item \texttt{EqualityComparable} is a model of STL EqualityComparable concept. \item \texttt{ExtIterator} is a model of External Random Access Iterator. \item Equality is defined between objects of type \texttt{EqualityComparable} and objects of \texttt{ExtIterator}'s value type. \end{enumerate} \subsection*{Preconditions} [first, last) is a valid range. \subsection*{Complexity} \begin{itemize} \item Internal work is linear. \item External work: close to $N/DB$ I/Os (read-only). \end{itemize} \subsection*{Example} \begin{lstlisting} typedef stxxl::VECTOR_GENERATOR::result vector_type; vector_type V; // fill the vector // find 7 in V vector_type::iterator result = find(V.begin(), V.end(), 7); if(result != V.end()) std::cout << ``Found at position ''<< (result - V.begin()) << std::endl; else std::cout << ``Not found'' << std::endl; \end{lstlisting} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \chapter{Pipelined/Stream Interfaces} %data flow graph, file, sorting, streaming nodes\\ %compare with TPIE AMI\_scan \section{Preliminaries} \section{Node Interface} \section{Scheduling} \section{File Nodes -- {\tt streamify} and {\tt materialize}} \section{Streaming Nodes} \section{Sorting Nodes} \label{pipesorting} \subsection{Runs Creator -- {\tt stxxl::stream::runs\_creator}} \subsection{Specializations of {\tt stxxl::stream::runs\_creator}} \subsection{Runs Merger -- {\tt stxxl::stream::runs\_merger}} \subsection{A Combination: {\tt stxxl::stream::sort}} \section{A Pipelined Version of the Billing Application} \begin{lstlisting} \end{lstlisting} \chapter{Internals} \section{Block Management Layer} \subsection{\texttt{stxxl::prefetch\_pool}} \label{prefetchpoolsection} \subsection{\texttt{stxxl::write\_pool}} \label{writepoolsection} \section{I/O Primitives Layer} \section{Utilities} \chapter{Miscellaneous} \section{\stxxl Compile Flags} \bibliographystyle{plain} \bibliography{tutorial} \end{document} stxxl-1.3.1/doc/tutorial/allmakros.tex0000644000175000017500000003736610647205664017662 0ustar andreasandreas% Peter's Makros \newcommand{\Id}[1]{\ensuremath{\mathit{#1}}} \newcommand{\vek}[1]{\mathbf{#1}} \newcommand{\mat}[1]{\mathbf{#1}} \newcommand{\ceil}[1]{\left\lceil #1\right\rceil} \newcommand{\floor}[1]{\left\lfloor #1\right\rfloor} \newcommand{\abs}[1]{\left| #1\right|} \newcommand{\norm}[1]{\left\|#1\right\|} \newcommand{\enorm}[1]{\norm{#1}_{2}} \newcommand{\sumnorm}[1]{\norm{#1}_{1}} \newcommand{\maxnorm}[1]{\norm{#1}_{\infty}} \newcommand{\xor}{\oplus} \newcommand{\set}[1]{\left\{ #1\right\}} \newcommand{\sset}[1]{\set{#1}} % synomym? \newcommand{\gilt}{:} %\newcommand{\sodass}{\,:\,} \newcommand{\sodass}{\mid} \newcommand{\setGilt}[2]{\left\{ #1\gilt #2\right\}} \newcommand{\seqGilt}[2]{\left\langle #1\gilt #2\right\rangle} \newcommand{\Litem}[1]{\seq{#1}} \newcommand{\Def}{:=} \newcommand{\zvektor}[2]{\left(#1,#2\right)} \newcommand{\vektor}[2]{\left(\begin{smallmatrix}#1\\#2\end{smallmatrix}\right)} \newcommand{\vektord}[3]{\left(\begin{smallmatrix}#1\\#2\\#3\end{smallmatrix}\right)} \newcommand{\condition}[1]{\left[#1\right]} \newcommand{\binomial}[2]{\binom{#1}{#2}} \newcommand{\even}{\mathrm{even}} \newcommand{\odd}{\mathrm{odd}} \newcommand{\mymod}{\,\bmod\,} % \newcommand{\divides}{|} %\newcommand{\Div}{\,\mathrm{div}\,} % Typen \newcommand{\nat}{\mathbb{N}} \newcommand{\natnull}{\mathbb{N}_{0}} \newcommand{\natplus}{\mathbb{N}_{+}} %\newcommand{\natless}[1]{\mathbb{N}_{<#1}} \newcommand{\natless}[1]{\mathbb{N}_{#1}} \newcommand{\nplus}{\mathbb{N}_+} \newcommand{\real}{\mathbb{R}} \newcommand{\rplus}{\mathbb{R}_+} \newcommand{\rnneg}{\mathbb{R}_*} \newcommand{\integer}{\mathbb{Z}} % \newcommand{\intint}[2]{\set{#1,\ldots, #2}} \newcommand{\intint}[2]{{#1}..{#2}} \newcommand{\realrange}[2]{\left[#1, #2\right]} \newcommand{\realrangeo}[2]{\left(#1, #2\right)} \newcommand{\realrangelo}[2]{\left(#1, #2\right]} \newcommand{\realrangero}[2]{\left[#1, #2\right)} \newcommand{\unitrange}[2]{\realrange{0}{1}} \newcommand{\bool}{\set{0,1}} %\newcommand{\boolean}{\mathbb{B}} %\newcommand{\mapping}[2]{#1\rightarrow #2} \newcommand{\mapping}[2]{{#2}^{#1}} \newcommand{\powerset}[1]{{\cal P}\left(#1\right)} \newcommand{\NP}{\mathbf{NP}} \newcommand{\Bild}{\mathbf{Bild}\:} % Typannotation \newcommand{\withtype}[1]{\in#1} % Wahrscheinlichkeitsrechnung \newcommand{\condprob}[2]{{\mathbb{P}}\left(#1\;|\;#2\right)} \newcommand{\condexpect}[2]{{\mathbb{E}}\left(#1\;|\;#2\right)} \newcommand{\var}{{\mathbb{V}}} \newcommand{\quant}[2]{\tilde{#1}_{#2}} % asymptotische Notation \newcommand{\whpO}[1]{\tilde{\mathrm{O}}\left( #1\right)} \newcommand{\Oschlange}{$\tilde{\mathrm{O}}$} \newcommand{\Ohh}[1]{\mathcal{O}\!\left( #1\right)} \newcommand{\Oh}[1]{\mathcal{O}\!\left( #1\right)} \newcommand{\Ohlarge}[1]{\mathcal{O}\!\left( #1\right)} % \newcommand{\Oh}[1]{{\mathcal{O}}(#1)} \newcommand{\Ohsmall}[1]{\mathcal{O}(#1)} \newcommand{\oh}[1]{\mathrm{o}\!\left( #1\right)} \newcommand{\Th}[1]{\Theta\!\left( #1\right)} \newcommand{\Om}[1]{\Omega\left(#1\right)} \newcommand{\om}[1]{\omega\!\left( #1\right)} \newcommand{\Oleq}{\preceq} % local reference \newcommand{\lref}[1]{\ref{\labelprefix:#1}} \newcommand{\llabel}[1]{\label{\labelprefix:#1}} \newcommand{\labelprefix}{} % later redefined using renewcommand % open issues %\marginparwidth5cm \marginparpush2mm \marginparsep1mm %\newcommand{\frage}[1]{} %\newcommand{\frage}[1]{[{\sf#1}]\marginpar{?}} \newcommand{\frage}[1]{[{\sf#1}]\marginpar[\hfill$\Longrightarrow$]{$\Longleftarrow$}} %\newcommand{\frage}[1]{\makebox[0cm]{$\bigotimes$}\marginpar{\tiny #1}} \newcommand{\mysubsubsection}[1]{\par\vspace{2mm}\noindent{\bf #1 }} % punkt am ende von display math \newcommand{\punkt}{\enspace .} % Pseudocode Unterst\"utzung \newcommand{\labelcommand}{} \newcommand{\captiontext}{} \newsavebox{\buchalgorithmparam} \newcounter{lineNumber} \newenvironment{buchalgorithmpos}[3]{% \renewcommand{\labelcommand}{#2}% \renewcommand{\captiontext}{#3}% \sbox{\buchalgorithmparam}{\parbox{\textwidth}{#3}}% \begin{figure}[#1]\begin{center}\begin{code}\setcounter{lineNumber}{1}}{% \end{code}\end{center}\caption{\llabel{\labelcommand}\captiontext}\end{figure}} \newenvironment{buchalgorithm}[2]{\begin{buchalgorithmpos}{htbp}{#1}{#2}}% {\end{buchalgorithmpos}} \newenvironment{code}{\noindent\it% \begin{tabbing}% \hspace{1.5em}\=\hspace{1.5em}\=\hspace{1.5em}\=\hspace{1.5em}\=\hspace{1.5em}\=% \hspace{1.5em}\=\hspace{1.5em}\=\hspace{1.5em}\=\hspace{1.5em}\=\hspace{1.5em}\=% \kill}{\end{tabbing}} % 1=pos, 2=llable, 3=caption %\newcommand{\labelcommand}{} %\newcommand{\captiontext}{} %\newsavebox{\codeparam} %\newcounter{lineNumber} %\newenvironment{buchalgorithmpos}[3]{% %\renewcommand{\labelcommand}{#2}% %\renewcommand{\captiontext}{#3}% %\sbox{\codeparam}{\parbox{\textwidth}{#3}}% %\begin{figure}[#1]\begin{center}\begin{code}\setcounter{lineNumber}{1}}{% %\end{code}\end{center}\caption{\llabel{\labelcommand}\captiontext}\end{figure}} %\newenvironment{buchalgorithm}[2]{\begin{buchalgorithmpos}{htb}{#1}{#2}}% %{\end{buchalgorithmpos}} % code in text %\newcommand{\codel}[1]{{\sf #1}} %\newcommand{\codem}[1]{\mathsf{#1}} \newcommand{\codel}[1]{\mbox{\rm "`#1"'}} \newcommand{\codem}[1]{\mathrm{#1}} \newcommand{\Assert}{{\bf assert\ }} \newcommand{\Invariant}{{\bf invariant\ }} \newcommand{\Class}{{\bf Class\ }} \newcommand{\Constant}{{\bf Constant\ }} \newcommand{\Array}{{\bf Array\ }} \newcommand{\Of}{{\bf of\ }} \newcommand{\Function} {{\bf Function\ }} \newcommand{\Funct}[3]{\Function #1\Declare{{\rm (}{#2\rm )}}{#3}} \newcommand{\Procedure}{{\bf Procedure\ }} \newcommand{\Operator}{{\bf Operator\ }} \newcommand{\Type}{{\bf Type\ }} \newcommand{\Address}{{\bf address of\ }} \newcommand{\Pointer}{{\bf Pointer\ }} \newcommand{\Points}{\ensuremath{\rightarrow}} \newcommand{\Allocate}{{\bf allocate\ }} \newcommand{\This}{{\bf this\ }} \newcommand{\Null}{{\bf null\ }} \newcommand{\Dispose}{{\bf dispose\ }} \newcommand{\Deallocate}{{\bf dispose\ }} \newcommand{\Delete}{{\bf dispose\ }} \newcommand{\Process}{{\bf process\ }} \newcommand{\While} {{\bf while\ }} \newcommand{\Repeat} {{\bf repeat\ }} \newcommand{\Until} {{\bf until\ }} \newcommand{\Loop} {{\bf loop\ }} \newcommand{\Exit} {{\bf exit\ }} \newcommand{\Goto} {{\bf goto\ }} \newcommand{\Do} {{\bf do\ }} \newcommand{\Od} {{\bf od\ }} \newcommand{\Dopar} {{\bf dopar\ }} \newcommand{\For} {{\bf for\ }} \newcommand{\Foreach} {{\bf foreach\ }} \newcommand{\Rof} {{\bf rof\ }} \newcommand{\Is}{\mbox{\rm := }} \newcommand{\Forall} {{\bf forall\ }} \newcommand{\ForFromTo}[3]{{\For $#1$ \Is $#2$ \To $#3$ \Do}} \newcommand{\ForFromToWhile}[4]{{\For $#1$ \Is $#2$ \To $#3$ \While $#4$ \Do}} \newcommand{\ForFromDowntoWhile}[4]{{\For $#1$ \Is $#2$ \To $#3$ \While $#4$ \Do}} \newcommand{\ForFromDownto}[3]{{\For $#1$ \Is $#2$ \Downto $#3$ \Do}} \newcommand{\ForFromWhile}[3]{{\For $#1$ \Is $#2$ \To $\infty$ \While $#3$ \Do}} \newcommand{\ForFromdownWhile}[3]{{\For $#1$ \Is $#2$ \Downto $-\infty$ \While $#3$ \Do}} \newcommand{\ForFromToStep}[4]{{\For $#1$ \Is $#2$ \To $#3$ \Step $#4$ \Do}} \newcommand{\ForFromDowntoStep}[4]{{\For $#1$ \Is $#2$ \Downto $#3$ \Step $#4$ \Do}} \newcommand{\ForFromStepWhile}[4]{{\For $#1$ \Is $#2$ \To $\infty$ \Step $#3$ \While $#4$ \Do}} \newcommand{\ForFromdownStepWhile}[4]{{\For $#1$ \Is $#2$ \Downto $-\infty$ \Step $#3$ \While $#4$ \Do}} %\newcommand{\ForFromTo}[3]{{\For $#1\in #2..#3$ \Do}} %\newcommand{\ForFromToDown}[3]{{\For $#1\in #2..#3$ {\bf downwards} \Do}} %\newcommand{\ForFromWhile}[3]{{\For $#1\in #2..$ \While $#3$ \Do}} %\newcommand{\ForFromDownWhile}[3]{{\For $#1\in #2..$ {\bf downwards} \While $#3$ \Do}} %\newcommand{\ForFromToStep}[4]{{\For $#1\in #2..#3$ \Step $#4$ \Do}} %\newcommand{\ForFromToDownStep}[4]{{\For $#1\in #2..#3$ {\bf downwards} \Step $#4$ \Do}} %\newcommand{\ForFromWhileStep}[4]{{\For $#1\in #2..$ \While $#3$ \Step $#4$ \Do}} %\newcommand{\ForFromDownWhileStep}[4]{{\For $#1\in #2..$ {\bf downwards} \While $#3$ \Step $#4$ \Do}} \newcommand{\To} {{\bf to\ }} \newcommand{\Step} {{\bf step\ }} \newcommand{\Downto} {{\bf downto\ }} \newcommand{\If} {{\bf if\ }} \newcommand{\Endif} {{\bf endif\ }} \newcommand{\Fi} {{\bf fi\ }} \newcommand{\Then} {{\bf then\ }} \newcommand{\Else} {{\bf else\ }} \newcommand{\Elsif} {{\bf elsif\ }} \newcommand{\Return} {{\bf return\ }} \newcommand{\Set} {{\bf set\ }} \newcommand{\Boolean} {{\bf boolean\ }} \newcommand{\Integer} {$\integer$} \newcommand{\True} {{\bf true\ }} \newcommand{\False} {{\bf false\ }} \newcommand{\Bitand} {{\bf bitand\ }} \newcommand{\Var} {{\bf var\ }} \newcommand{\Xor} {{\bf\ xor\ }} \newcommand{\Not} {{\bf\ not\ }} \newcommand{\Or} {{\bf\ or\ }} \newcommand{\Div} {{\bf\ div\ }} \newcommand{\Mod} {{\bf\ mod\ }} \newcommand{\Decrement} {\ensuremath{\mathbf{-}\mathbf{-}\ }} \newcommand{\Increment} {\ensuremath{\mathbf{+}\mathbf{+}\ }} \newcommand{\End} {{\bf end\ }} \newcommand{\Endfor} {{\bf endfor\ }} %\newcommand{\Rem}[1] {{\bf (*~}{\rm#1}{\bf ~*)}} \newcommand{\Rem}[1] {{\bf //\hspace{0.5mm}{\rm#1}}} % rechtsbuendiger Kommentar %\newcommand{\RRem}[1] {\`{$\mathbf{(*}$~ }{\rm#1}{~$\mathbf{*)}$}} %\newcommand{\RRem}[1] {\`{\bf --\hspace{0.5mm}--~}{\rm#1}} \newcommand{\RRem}[1] {\`{\bf //\hspace{0.5mm}~}{\rm#1}} \newcommand{\Flush}[1] {\`{\bf \hspace{0.5mm}~}{\rm#1}} \newcommand{\RRemNL}[1] {\`{\bf (*~ }{\rm#1}{\bf ~*)}% {\tiny\arabic{lineNumber}}\stepcounter{lineNumber}} \newcommand{\Declare}[2]{#1\mbox{ \rm : }#2} \newcommand{\DeclareInit}[3]{#1$=$#3 \mbox{ \rm : }#2} \newcommand{\At}[1]{\left\langle#1\right\rangle} \newcommand{\NL}{\`{\tiny\arabic{lineNumber}}\stepcounter{lineNumber}} % Beweise \newdimen\endofsize\endofsize=0.5em \def\endofbeweis{~\quad\hglue\hsize minus\hsize \hbox{\vrule height \endofsize width \endofsize}\par} % gibt es in amsmath schon % \newcommand{\platsch}{\hglue\hsize minus\hsize} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Kurts Makros \newcommand{\widebinop}[1]{\hspace{0.5em}#1\hspace{0.5em}} \newcommand{\donotshow}[1]{} \newcommand{\maths}{mathematics'} \newcommand{\apostrophe}{'} \newcommand{\dapostrophe}{''} \newcommand{\ignore}[1]{} \newcommand{\pnegskip}{\vspace*{-\baselineskip}\vspace*{-\belowdisplayskip}\par} \newcommand{\proofendswithequation}{\vspace*{-\baselineskip}\vspace*{-\belowdisplayskip}\par} \newcommand{\eqndot}{\ .}\newcommand{\eqncomma}{\ ,} %\newcommand{\qed}{\rule[-0.2ex]{0.3em}{1.4ex}} \providecommand{\mod}{\mathop{\rm mod}} \newcommand{\conv}{\mathop{\rm conv}} \newcommand{\F}{{\cal F}} \newcommand{\dom}{\mathop{\rm dom}\nolimits} \newcommand{\op}{\mathbin{\rm op}} \newcommand{\mes}{\mathop {\rm mes}} \newcommand{\ind}{\mathop {\rm ind}} \newcommand{\size}{\mathop {\rm size}} \newcommand{\fl}{\mathop {\rm fl}} \newcommand{\cl}{\mathop {\rm cl}} \newcommand{\inn}{\mathop {\rm int}} \newcommand{\cpl}{\mathop {\rm cpl}} \newcommand{\reg}{\mathop {\rm reg}} \newcommand{\bd}{\mathop {\rm bd}} \newcommand{\bR}{\mathop {\rm bR}} \newcommand{\loglog}{\mathop {\rm loglog}} \newcommand{\CC}{C\raisebox{.08ex}{\hbox{\tt ++}}} \newcommand{\Cminus}{C\raisebox{.08ex}{\hbox{\tt ++}}\raisebox{.25ex}{-}} \newcommand{\GG}{g\raisebox{.08ex}{\hbox{\tt ++}}} \newcommand{\Gminus} {g\raisebox{.08ex}{\hbox{\tt ++}}\raisebox{.25ex}{-}} \newcommand{\R}{I\! \!R} \newcommand{\N}{I\! \!N} \newcommand{\Z}{I\! \!Z} \newcommand{\Rp}{I\! \!R_{>0}} \newcommand{\Rn}{I\! \!R_{<0}} \newcommand{\Rnn}{I\! \!R_{\ge 0}} \newcommand{\progitem}[1]{$\langle$#1$\rangle$ } \newcommand{\strecke}[2]{{#1#2}$^{\hspace{-.6cm}\longrightarrow}$ \ } \newcommand{\punktstrecke}[2]{{#1#2}$^{\hspace{-.6cm}\longrightarrow}\ $} \providecommand{\3}{\ss} \newcommand{\la}{$\langle$} \newcommand{\ra}{$\rangle$\ } %\newcommand{\Litem}[2]{$\langle$#1,#2$\rangle$\ } \newcommand{\Listitem}[1]{$\langle$#1$\rangle$\ } %\newcommand{\range}[2]{[#1 \, \ldots \, #2]} \providecommand{\range}[2]{[#1\, ..\, #2]} %\newcommand{\halfrange}[2]{[#1 \, \ldots \, #2)} \newcommand{\halfrange}[2]{[#1\, ..\, #2)} %\newcommand{\precond}{\\ {\em precondition}: } \newcommand{\Kurt}{\htmladdnormallink{Kurt Mehlhorn}{http://www.mpi-sb.mpg.de/\~{}mehlhorn}} \newcommand{\Stefan}{\htmladdnormallink{Stefan N\"aher}{http://www.informatik.uni-halle.de/\~{}naeher}} \newcommand{\Christian}{\htmladdnormallink{Christian Uhrig}{http://www.mpi-sb.mpg.de/\~{}uhrig}} \newcommand{\LEDA}{\htmladdnormallink{LEDA}{http://www.mpi-sb.mpg.de/LEDA/leda.html}} \newcommand{\GmbH}{\htmladdnormallink{LEDA Software GmbH}{http://www.mpi-sb.mpg.de/LEDA/GMBH/gmbh.html}} \newcommand{\SB}{Saarbr\"{u}cken} \newcommand{\figlabel}[1]{\label{fig:#1}} \newcommand{\figref}[1]{\ref{fig:#1}} \newcommand{\Hline}{\hspace{0.0in}\hrulefill\hspace{0.0in}} \newcommand{\uedge}[1]{\sset{#1}} %\providecommand{\path}[1]{[\hspace{\setspacing} #1 \hspace{\setspacing}]} \providecommand{\Path}[1]{[#1]} \newcommand{\seq}[1]{\langle#1\rangle} \newcommand{\Exp}[1]{{\rm E}[ #1 ]} \newcommand{\prob}[1]{{\rm prob}( #1 )} \newcommand{\disjointcup}{\mathbin {\dot{\cup}}} \newcommand{\Kmarginpar}[1]{\marginpar{\footnotesize #1}} \newcommand{\mbegin}{\{\ \ } \newcommand{\mend}{\}} \newcommand{\memptyline}{\\[-2ex]} \newlength{\mleftindent} \setlength{\mleftindent}{\parindent} \newlength{\mindent} \settowidth{\mindent}{\mbegin} \newlength{\mboxwidth} \newcommand{\mincrement}{\addtolength{\mboxwidth}{-\mindent}} \newcommand{\mdecrement}{\addtolength{\mboxwidth}{\mindent}} \newlength{\preprogramskip} \newlength{\postprogramskip} \setlength{\preprogramskip}{\smallskipamount} \setlength{\postprogramskip}{\smallskipamount} \newlength{\mexpwidth} \newlength{\mexpindent} \newcommand{\indentafterkeyword}{\hspace*{0.5em}} \newcommand{\mwhile}[2] {\While #1 \Do\+\\ #2\-\\} \newcommand{\mforall}[2] {\Forall #1 \Do\+\\ #2\-\\} \newcommand{\mifthen}[2] {\If #1 \Then\+\\ #2\-\\} \newcommand{\monelinewhile}[2] {\While #1 \Do #2\\} \newcommand{\monelineifthen}[2] {\If #1 \Then #2 \\} \newcommand{\mifelse}[3] {\If #1 \Then\+\\ #2\-\\\Else\+\\ #3\-\\} \newcommand{\mtwolineifelse}[3] {\If #1 \Then #2\\\Else#3\\} \newcommand{\monelineifelse}[3] {\If #1 \Then #2 \Else #3\\} \providecommand{\Path}[1]{[#1]} \newcommand{\mindentcommand}[3] {\setlength{\mexpwidth}{\mboxwidth}% \settowidth{\mexpindent}{{\bf #1}\indentafterkeyword #2}% \addtolength{\mboxwidth}{-\mexpindent}% {\bf #1}\indentafterkeyword #2 \mbegin% \parbox[t]{\mboxwidth}{#3}\\% \hspace*{\mexpindent}\mend% \addtolength{\mboxwidth}{\mexpindent} } %--------------------------------------------------------------------- \newlength{\proofpostskipamount} \setlength{\proofpostskipamount}{0.5ex} \newlength{\proofpreskipamount} \setlength{\proofpostskipamount}{0.5ex} \newenvironment{myproof}% {\par\vspace{\proofpreskipamount}\noindent{\bf Proof:}\hspace{0.5em}}% 0.5 before {\nopagebreak% \strut\nopagebreak% \hspace{\fill}\qed\par\vspace{\proofpostskipamount}\noindent} \newenvironment{Proof}[1]% {\par\vspace{0.5ex}\noindent{\bf Proof #1:}\hspace{0.5em}}% {\nopagebreak% \strut\nopagebreak% \hspace{\fill}\qed\par\medskip\noindent} \newcommand{\highqed}{\vspace{-\belowdisplayskip -2.0\baselineskip}\par} \newlength{\mydefwidth} \newlength{\mytextwidth} \newcommand{\myurl}[1]{{\footnotesize \url{#1}}} %--------------------------------------------------------------------- %%% macros for use of the old book \newcommand{\textdef}[1]{\emph{#1}} \newcommand{\betonung}[1]{\emph{#1}} \newcommand{\usw}{\ldots} \newcommand{\alphaq}{\overline{\alpha}} \newcommand{\gr}[1]{{\mathit #1\/}} \newcommand{\rmid}{;\ } \newcommand{\case}[2]{#1: #2} \newcommand{\Eins}{1} \newcommand{\Zwei}{2} \newcommand{\Drei}{3} \newcounter{abbnummer} \newcounter{plusabbnummber} \newcounter{zweiplusabbnummer} stxxl-1.3.1/doc/tutorial/layer_diagram.pdf0000644000175000017500000032024711437171771020436 0ustar andreasandreas%PDF-1.4 % 3 0 obj << /Length 4 0 R /Filter /FlateDecode >> stream x͎u8?O/p[p=u`7(_Z\O|L2t%("u}~>r}^[>rl+?rIG복1R?/__+]?ǟ>Si}qczՏ_Wk룴s[-|z%YKUuO"ѳcLc"1ڿ ac8rGm`i<NZscxW|^su4I鳧r}_,5>~9rv j1N0Mt314gDMb3qR|ΖߌU1Ŵ*džNj9F|Nɕk9>qR{j:& ۏ۟7uoީJJ{y/RF׫zlؘ)]ic_ s[=poYlI@{{X馮,n(}|qSrA*m9b\o0~RMnti]ܝ61a26@.r)xq`Ogi[h [V^^=ou P7uvS8nl$n>z}> wO'Z97zwQD`&Z}0Y>w rKЯhpK}nrzVLb ]/լFZm .=_bчP77zMசMg5W `.֐56/c_!3%33#}+$&kUO6ǤQT?D[d͉;qo qAeM~4rB3Ah."7@z q6wk_|G4&Nss`K쑮˷]|q7_}9bssu'6۠}~jVo8ϿM7[yݡ?}7~o[ͱBxoeZK\}O_[LzeM7J uhFW/;kOrsgx6 L#/.YQ!$R0tFVсyŻ 4>FO,C}/ɸTc?g¾c?e75֏^ [/P]l6-? vO6,|=ryT)uNKjM9? Wm\Ǹw۩-[ֿtռgqkf{A<q &]@ ̨r>j PmKKkVW-f>;??d=u,b_ܘ#=8SV+" =m`8*wjGZy&eekowoc7^@\6~< M'+擷N~O yG;aw 4]2 ^>nH!0U`ır̉:׻ adMf# fIW2k/q$[\ b˒}øVt &~q:%8$6tX'~*9fGL_~\#ۆȧо0RK?[9_f {[߸'d=X@!csIr`Zz•ֺ F2ݒG7^1mqyr&}p0_6jks~ I&nO6UZw݄YnKΡP˖߽Kb#Q&BZX7&BI0QV#\N-L"ף ZܚrAz"q7xFI}qwv "utwfsT0qUb!kL'R`]dhKG>AJ"q? H|$2+#'d vm7@ȓ&s=1Dr-]hX_э.9Y C͓7 `..5yc(߾hNG2ZT^5X0Y!Wa ̭{sj:`7hIdgʳ!Lb#imi$ع&P‡}Uj5 ˔`147J(9rv`+l3*GJ}{ Dqe7W7J5g.*p~l%a񒹛L4ZL2{Zjcr/0xO)~J.{6v\m({%b㓣_$HN,j7^o`mHwɛ%uaI đ׊?ݱ x.8SzJQhj$#IUT)--i>4cֶNiu=SۛLԜmenV!a4۲MuvfI-+S7wl e?nTIxPvs/py"A@V u: 'fc"tM NDt&;il 20ywc~|v6㯏wQ;UO1egAA+`;]J^s sv0|T'7Xx}TBRfscøbc.T3? 9np̺Jℨ30xXVz/3JO6:I6.L,z6qQEn;Ѕ9ƔMe6&0Ei9PɂgvΘld3\\ۢ.iQo/20&E2Mt,>{X8BiH+n8;>H"|^vv8LH3crXwF5ukK7e3Z4Y#KA%ld[7cmBcR`*$X{n[*[49wۨ)p]l+p=bdމ);Ġ Y=Y\]4)K+FRUJ ~xagn'F0t?U>FgAos$CMW*me}1.z\#>p =B 8FXpȷ$S+N0nf+bЧ;o1B%ĹUJ{K=*!ug W~5p>j",),{3}[izR 8tBǸR8ݮ+Jt㰔Br&k~=\MM )0a,3=J(XPC-<0 'S jk"fxϵ"{l g}+~ƛuH,7뇇AH1S)CZ:C-B1D=!>,oaS13>,}{penRlH3AC5u )ʩ@sj6[wTLu4]pk^t~}ܦ>>f[rlUeVw () Z8\|1(A!&K!]|ք˱J8K>=;Ƿ̴E<rޑiwÿ$^ȿwv;=0L^P0o)=ar p{8)$s<&5wҲaU6ȀB$:4F.aOHGS,r]trb/P=a'}AJdBs--w-W;8cmgIF Cfk99(FAfKaOpE9esV6f_j}пK= Rʰ{oHWê/wf}}Cǽ{\smنS2qw޽6֧([]Onsso5D4h)C~ g=HҥJl&rQҵu40wG Jrw"׌_d]E72hFm4*M:〉9#y]t#Mؠ7F8{KiڟM. 'cj+bs D8Zh-Lk0r\k! K?V/34悕YT\ۤ4ϲ-'lzc\oa2uSD(,/&08SwͅOǡHo!shq\L`=4YCo!w ~F%F} +>Z?k^ƙ֒4r:Dq𒁰f>^[m!II֒#j˴[1+,)-jQHLO0Mflo7bPGP Иff0cuɸI~J WPZ8%+rV:˘`-&)-\R]i!s sٞukUnJ46w[h-.6Cѵaj taTvO6/c3Zj#fSʵhq]&Ba#A3Qb2Z~<:sPGLM`Q-F[0`z00Ω`$ ,IO< q{00-[ FK`$ 2)<&ڂ'34br_oi/&Y,0U Z|10bA]Zl!79]{0'H㏜/Ւ9P_L;\dZ-k6&lYTȈ`xX><+[7 <܎ѷ4iϫbAJE]T-u.D8HZ8mPIc0縬Y-# gېfmA)e7Huϐ;>;?|~`A;/iL/E7Ps kYG$t$ TMjD"?oC()~47j)a?~-eO  3]PaFuH.(iU܂B~.Pe+x2>p[STt[Ҹ(Xڿ0j %\? ~ӡ [wqn_? 1ocHE;0-{l b xS/3(Cտ̠M['ad!P0Ϳ(5G$;W2U1,A3<@#~ceH)btRB"2:HaM^iËH0غq3tbW)".9Ȥ,k+ (k|XbY0)HK !u7֧RXfhwݺ_eINN3W)IMLٮ0b 6&Ů^6Y*zwCQ Adp3"QCW naʵý ⿰pNBqt’1g㿀0 X"o_%4ʍ'+იycZ #dbg_@Jpq}K}IדtٰЯz!N cN=sz1ՁSUpxmodzG1@Q7㍣Ant̾C6b"ΜoЉ@/9767xcN:Vxnp/…$V?㍩oH+Ӕj(Tܒq.P09_ >n'_gL=DǤxfY}V>t C@hODڇ}-lc0@zNuES㽮q긫 rW8'ϲ yXIqQ;i['M9N 3)RX=-ʬyNuCS<8W;mjmƅ~Mɜ03l2M}aG>k $L>I엩`3]K x@63~v1 rR@_ Qr`n5^rH~͈I6M{ƫ\-WɕSiWẑ cRn@~xisDFwq^0Lcq#,1=^#/x-Tx[mo\QȜ/vN| n}llj}ڳ)K0c1&{c,r[µW3Y3M%'C3&G1e9a/+;(^\c>a( l_ )W’);~Px&ta.Ï/T9l=ܣwMds<<&b( c:Om`,n%x&Haَ\yG ޘm=o84٘RQ7B =1xpApP<(y#]7u>}8q WdDɭ01Ku,YhbJ\R3S6RыȢv¸*K >Kjy4oG:b6͚x巶p I%+ N. aI~íL)b \,`; ;x!EB3.}y Oi[84QǃNJXšu1_v~ |ys)yv iXR,K: "u¹R|Í  u#'qaҠ0#^yTYx+I~UJ!qrvLxf_C[VBd(p7E 3sܯn.1  _hqqlуjP[ EC0KhuQ"E8Ҧp`-[&NL1RjCQbieJ$Î\ƒbǙpXɫ}(dcl4c#2wq|з 5Ė<0[@>T/oC_K n姮u{nյɅaY*Snjr=+(<5~ҟו}IZ{;hmB+,M.}w?;J/|œViN+t2N+`iUՙyo+R@IX\ۙx\n1VPM.HpaNie=NrkIl Mm[dDrZ^(OUӜViutZ|8YiŹN+ i_ pN"- )oI-gcN+tZsmN=Vi~OU|T?V$iӊ|8XtZq*mj-#3AA:,s-rUYzJ瑽M <.Ԯ,@ŅǜAFm&{W#e9 "OfYJ@Ȋ('~,.ົ` o0{8|Ƴ0,wC}y(wܮiM쉮e9g{騇rz>8?y[;:lFimL<L-]-]#K׼$05/pSXz+Sg.)cꩯL]c#[yov ؅a2tO5/L%4;\ZwT9d 4/j㐭u=G7άcl-\~#I>,<iVj1A.6Ai nz$ g-.c]| ]I YbOϷeC1-[^Jd9Vm7f*֛AdmfOz^z˅:LLR< BA T{{sdqȨa-/yX9;:•OМSc1 n(a?f?G/+oHShjH)u,D=ԙ ÌԪ79蓟7+W>bKSkgQ@\3rP]r*8[>e-+"]U".gְ (Z Or\џj iXΕ+q=ĆüYnb4 x(=5J2`8 ]GSUYdq*#7;qTg`pqF{ATǥr%$x5 I-J"mX [՛HG{NL. \ _&n _#^^QNko }16#ElYJaw1VWxهO,}UynXPK aQPi=^Ym=dY,ر ({ōS+ {iFdR ?(`X=(`h y4Gd<ژR^և[ 1S.m ^Ƹ[/y52M^ÇÞ_Z)suW.0fNH[l]=|VlIfν&`rɃwb&]Ym081`ksjat׬l2n>oIw# "~JU^9J%PDvOnH/OI¼syPk<@ L߳,pS?t|"\]xM(O+OXW4w.:3Me~2w5'$64#SO#D=U4v` y&=8v G*s.NodƄɕ9͕aQ6{uʻ 9dEy7ߝW .Z=]$B]ۊP~ WS") (:AdgTRR{C[vh`E~ʯ/-8 %aC.r 8N^RNry15G\AP )@P#P`1G?+#|_6PSv^S~Qcg jt"瀹?e/!rQi$F&dތ;ݦl,Ҟ2 zҦyW]4ݬDYE\DvR‹!Am)rC@-xnd +vg.ڪK3FyY7Υ^)G.uExY(2AxN]VLKp}SvK9S-81G.u`ڑKp$y]H6-&r^= (\ V9r;Y!콯[zhzHK$N OG.uȥ>s\X"ފ@ט5s1Õb3zMKsg.'`p{G.uK|R7&\RMmG.u.ΥNg.uK+|d>r\@#6cRgg.uљKȥQ#zȶȥOA۔3H{ )z)lv.uߏ㿾Ϗ>, T{QNa#<__&4*%OQ׸]vU;?ޔ?kݭЗi2w8LwQ FɊ~ו1"> כ.Ͽ_ _m2SøC* 50*s&˸:j ?YqyL[uCt/FMzg'C+b \ vU6OF~^͢YLԅ-#RIklBDݲxYˮ9";{7\RvxQ>@LEwy+d6uSlp.51/7g=1˥ۚV'$ 2 ~q7.:Y& A"ؙݰSX:<ټ,_lkI0|=Q[잗nSەYMݖښiq*6ݔʘnyݗ %MEṵ2qY|d,j/x]O;cYcC7s~n..~n0eiQ.LEێQhC(acc9(=8bK9+ rp0Y? ;<->;=ىzM2VUe+"K y>y&^-qdWe͐%gr We!S5Xyݠ̗R/| ,"sߤM MPTC>-8т2av6hdegS&IZ4]Suį^:Uy, ̛@0Ęڜ'wMTLlqJ7cٓ?C-/qoe`mgeQ]FT^q%U oJ,[ CL];J9CbSdvՏ8eȈ#@e;LVuSoE1*yV#7CFѯ0G/YYib\I_T|)pR,[E{gΧn2LVk+VH)+%D%2Vwsl۫Jb4+j2XRGoz%fkavPS.y;hŨ*;iSzP +o$ͪI {nSvlaX3T`X,H.ui2V2łYB 8i?Xj+2*jwRBIGe|[?4XS>wfFBGFudEwqiPi1a,8<;P{ꕭ`[I !1 x:ʾLNm%Ók{/?bY@J*lJd푣p!5*B˗O0r x.4*IUbR_1']gK"pʊ\@ 5\̪lJukLRWz*mq.Y`Hx$"[k_,x鮮"ʕҗµ?%_ ]QM!Aظ8%jF=S*YJVƤd97)@rqv-~ljVqٔ.ׇ2ơ+ǩf[*PtmYSʠU\N/,)kr5qi^FOe$vZq*~VOŐbnÙԻXW'$PY~s2>ZEfD15g=h^ffTふM-'Pi LrfMKSӮ70tE-_)#Fe7|5dpV AlՎkc2cLI#gK Vwtx|q&g^^qX9߯f#c^C\^mZ6VNUBCޘP߸?4R/ڍi~5FBԊr@߶:6jekKq!ɏt"ȭ]oaXjv8IĮ>q J5-Usk>!⟧+ 8!ax>g \~D,CsM\V=HMI{w,l67i&\3e;B G&e,w ?S7enٟ4F囇-wmMݢs}R4T窇'[O/$ߧeeSEeg،geک/u9Јod)d7,K),j0-%bf{/E~R+?=R+T}^l+0!)RĽXBB~b.՝DQaGWN쟘Ph}cq!W{K氏}@9moisbIUB7X[u]Qo֢?Hޙ X.7Aang p*WXT#.pcf7R@8l_,mUO3",cԬϯpƘ@U%5@q]9e~($1(s6qd㳸Q#YO;ȧ;h]tTMK[EfUYg,LҨ>$a^ԯmzjKfeWMlqf BHZٙnٙT+Zt73WV-YyD,bbʆBQa-Y4?#“g= !fUV+bKY}ýN3+ o﯏@cga}@T@. LVRis!wj[fX_ʌг,gYR$.#B/]nyrƢ7 W\'U,*Rڲ^k),ƧOxRP zbT8/3*s!Fby[e .e)0"zW חr̦˃x+`T}s߸1)d:b1OU[GrG90R0ǭ4VP-:nǭ 0d[2 $E-ָiheѦC5 t [vv+D jǭu joq!iDVPk8J@_VxnT{8]zo j(TQ[ZFx=bP8BUUG՟E>F}1IbPYI mfm#)NGlOSB`Dė-tv>l/5͡fV]PYU,@,]Ud|&ÊPXm28]T/zN>2ܷw:/ÛicKF7v}`B&?WҊ)+d/n Mj&J-@I*nܥɺ8#KU [yΊj݌^Ya`RFe( Z9^-+|E,:t4#8Ԕ׎рcGz0#ۓl'ba%]n0/30O#H3x8YVU՟Q<9xnW nTv 6 {D J=\ĆeQ)9#rͭ5*)YdOIt6&s%% g<%刧OOYt r-/j7IOɊG<%JO zSPMX:_IO!a1HJ)A|DRķ20 8U!1d#=") Ӭ>d0Pd5"2g$O~DRcHJ눤|Snl,f2#tDRb툤?#)@r4!U"vcKG$%grDRό)ږ]Ve4dbֶT,=K9`nauc?iz\ xa=(VSLq %^l{X>7vN4J>]Jۀ H̐jXM|ӆES SwyoҬ{`^ pI>U߲SAY[t:zaQL\aj)>62(L~#Fz նAHm|x $QjYxF r'lƯ w?k{ao"rs?0"q&V{Suv AZ*nbX< c啡k6`Y0X%e=l@up?mMƲIW`ur=X^= RK'BI˩`R"NI4r o:(6a鲊N78$ƪD2sMMDŔam6oKmmݟ Z+`ufmǘoȸǽ-tق1TΊo@Mp |D-&fgRb ?TØ;UlzCƝ6F3ˋgg^Ek`G{{ ~U׹e>Rvؘi(-e(1k[ޏGKFYUK:b&^~䥢> 5le >P&CB Q (XUj>a2 )XrN,+2O|oΪg.bQX$uXi"c\XX 7ʏH]D]{QcW՘ՃyZQ(b?W|lbk!jw$b4ERI?ĴcQrt. X ҡ(\QOGf_;([pQ;+r>k$1ɰJ (v`Fq-G=,G߫ U/K +C@]MX։Yl=xABb3f1Y )gV޼b?NhQ$,zUAώ_͟ jpⲻ݅[--5dv;r-B7^g7L[Bbv݊b쏺xC-wWln2T}yj*Yuϫ^T#<2p}COoϧn|.:mmKh%'<ϸ_اgz+w Vhͧ#P,g~>(CT"^zok5}ޭjx\~Υ_2}z12?KxD\DɊfzzrw#Ӌi9ϰ) SWhz0YwL=)AQEc$aIT\>.j)P{83ylkL2 .IF5^:g̭N_ Ҁ[/b\p DZ镱2QD xn%彋,S.xQrys"TGLcC-avLps!mm+f#0[D HW\gG7㴷X͒n`_=s&Jh RvSnym܊[Yv FjXu­%hGXQo!Nwn^'RWnp/9Gk6=qde^.?11U|*Tč(?m-<,݀uiOܰס p3\ 6 g;pXQbyQQY+޸~x)R-8= 4LrnDY9ыpxr#o*L45Boky7֛,oZq1 'QHR 7X F;S$o0Ca`=(,8_6`1+@i^3LEyxM97X̋ygZcy``*K—f65C Ύa6{y1f=])G#*t%}9HKmdGee"p.-4ߪ$KVK0R&ʻ]bc>ecZx6Y OUtk Qy!<7 [d~y77}0nF$%?1wY;))(Ml70=Tc'{8ʰI*+[%Iob3fb:$Pj 6 q-|ݬЃڛ_ 90<-gj>Ubgݬ26AQ-XQP8J)nWfZF>, Miބ);85Y9˻io&랪ƶhY&-Lwo+ ^n霫˭ȪJ Yk#>w?dJ}F^g Ñ}"ILYeYh)KT¡'Y5J1[4wՕ+>RTֈ\W|>j^P.{&a^̌K.t |# |3k.}v$>{ǿ[LA`6߈9GVk]`Y4-ۊy,yn(6:9npzVJr)ُK[>‚Tx*6s4][_0]\W0]8|z,⋹-KCsLP2KeWEA:}H}L ^'=\j]jUvf/Gʂ)'Sߍ^I[i6M_A߭e-UbHĄ)G(^ y"`L0 S2ȍHgh:n6&TFt+`:HhE6 3U^@xs!_`ڭfڰ\l^Y$?o3|=Dڒ=mxz[Y+䞝Q^叿'T+(1Ωs/Kgpܞ[Z-rَvPm^yp;/mW] xoG9W1"e=6 H poGhcIb7 7%!06] nt[q%/i+0(Fb0jcHm6Pݓ.Pg^#t/hJ[=xf7r N6>JWĊon{navXhRlOyIgcdҡ̀:t4 Ӥ<+L: ,;ӑI0(2eaât՗&hfmFC:Zt}sÜ9x&|baq{6c9aR֨y*aֹmAfqshNa 997sѺ̒(}ÞC[B3"[Vd{pXzT`dAlrd6fbryz2ny9DąC>Yc>kKQT*^=T,}|tf?w ajj/{UjRjH|(0+ҽ2AwO6kMeލ/NS \}'>Qip7|y<fQif |,̷Dϛ)fڈ( FTq6rKOy LOLuNu~. .v2ݍ*#pQdy F{G BK=ϢZy?1QvT=9?oΐ3PKQ q_-}cy=%g:o1E=oxd#)8H Rz1}w<jl|.*zȑicqՍ2K"bj\;\]W~S-(F*_Mb`]c 3.(&4Ϫ1ݟe1*ʳ M7Aܷm]mm=m֑u-.«nJC9 "OLUw'5re6O8<}0F`%$]&i9F: ִO 3XB˧=0Wu|w->=m~{[ancHe s=L$nToii|~uP NؔF1sr *wi+2XU\P{}'aG[O1%8 իv̓q$y,Px&o0I|$Śɵ-[s0j2麂-g ܏g{]|0ȥoq^CK,o)Al"J(p8H/ [eM81`rO0|GL WcȈ>R>a"WAŮz+&?L5NE4"`{m^5yf^{դpް{VU,Re3{T7^of00N S<&o _vЅpѪIYUSW-h# B&e 0L_55=gM_W>agJ^S.cQkZX n^ru5+r0mٹ 3t0'PkN.'SpR0ꑋ]iko͗TS/7|8bs&0xPhybqLq{wOB(أ oHURc,C "YuO=!tLV=Io̷}YtK=Kac> :6^xG叉Xxz)ܞ;e*K@|T._%px0F)/+:SY:#b*)&qcXm#+["@+5`GK{ pOz$6J)IPʢg H/<^.W,3~`CB> U~E4o$z5:0Ym%A(P㩗, gMogK3+rRɬcVR|$(Z QZJU:s`f O@oEf9> OsVXjCS1w^LlOa=AJ5 pD؞i= CLpv6=/rV1vb=i}-)`[04 {pcN"tП'v|u?lٕU$[T HCX w+v!Fz,ddg3#Au"uUZ O sEG-2p#*y`TYЇZbiB- [:j +}!eJT_ǩ\a|'JYb<ѭ^E;/,;*0E6o0?P9.C% +/hgze[t@"D⾰pa8d!`^{G#lsẁmۥ JP0o7aFj,s8EDFYVv]SIJe@{\ZڙDܼiKV}כH$Ji/ @:6F.lez.4Sۓ%B8Rpt ۨx{)%[ԭ!ëjIk:]QV*'wf "ectzlhl3/jv^afݥ>%O;A'xȊq) -Y1.13P})1it~5[f `qTIޖٲaWvh+be:|ZOGd`IK̮%Ŝ,Ԍ[.em(|JCr-`fϟoa3gfis J3dV$k:d1{$^mVslin϶&mlؘ9H;1I6Lp16pZfeBB0س#1eR rռ|cyD,Ko pV)!Y6.w4 y.!% يeC@"!  c~`vKX?Y` ~қDik-[R .|ļdvrV5uqrG"hE (7-N,lf]pI@f֏- Vc*g!![B._,Q]--q#HH+f`XlS(y#0#i'*s@YX*MCS) a*Jh`b,vq'D# (Yᖨ6&<6⿥3O Bt| FLJ ytur6|xpyj ,-&+cvGذlL]ûJI5?鰘.Rs^n!yB E&WΕ 2'Flzy.=Dn XFau_t䥺?ow#\@e 7xBu}_|h3;<}VVz|E'5I~]gϹ\ͦ{6X=F-eT`ihl _3sR2rH$"$ޖX>qxeU!NyypPR%"ՒI $R"&&6*4>~cUÿ9% u̩G*?;_[Ӕа*e}⹍%,'b`__kܱ&Mg'iF KI6X̆;qJ^\`@Ok$ XMxG$MEV^&JʌN$5ɬ)@!3dG)Of]\wXr$@0+J8 =ge/'uC9>(/I7̓yTA( ƀTgCfǖl/~n1죓7@3$ P/0k$Mf׆4]()XYJs .VԦ2bV [{:O,6;URIycP/n:ld%^P˾x`ETtXD!pr0D.go3i(%O%Qђ½EIGTK40|2RqtuH 3;%\ BD)l^[Zf!!XH ^0$\KLceҶ7 p\k FPPV† ŬmS;>A501>94'e쀣Лal D(#^Q# ',|YCJ  77] }qT&0c y6額/Rï;*_crx}/FV٦E2Rqٌ<5M^fDN+:܁.{,avIzJxTu ٦*HHe79%u຅UOhJ+]ө^F ½ISs~DRg6-;O%&hBuEEmF')6LyZh&s_B%oG0.lmbme=  DOǺ؜ϗC%2'4TE9nJ"0M3%^F2&T(Eڝ3* ׽H(r$Ȳc Deq.߲P08y?v}r꩓V<|  u7}mH5iGi1+S@j2b,|M8&|}lUq?_2)7 Yhrg ghM".5皫Z˻iGnlkNچޱ!qJI 9z : :S|ìF_> ^qc+_ԿU4! 2 ñ3^0lr>Osϵ]|W ,tԤ<2\C92B"언uvR.I,erav o HBvZ*\yԌݓIYᖒeb:M2HdPV,<*M BU-@ig!ś -l@l8W]<;@f@͖,fc knDSBj;:ɟ4vwB>IlmQ; Kl0|CaGAN5iyv7+L+ҎD|]>B M2Eb;(ί. 53/9_/b1h}ܟt#!"*XCLQ[͵vx7Cֹϑq)d%(%t6 S)02Ĺj89vQљTDf< EnA Jyögq _uszަiTjH>f\2 -$,QsS+c}\9;]oe^DZƽ[ҞN- "|W|4t? 7+t_+ ЭybJbZbf_~}?M5]nmSZY~FA%־U knf@NBc rIơd vco~z!=0r:"F"DO(IDB ]qC{!=*d, Gi*,o"X[Kֲ/2OƹU5kUUVKzsc n9*vQyS= G̒V@Y4OIۋ4ʅSfltX2㜲hg^(@ &L_Į@͑j"xHH sef{W,`g[M9Wz*z]׭ Y^*HtƮ=4O|$N }?я0薂nV HAxȹ^4X* }F1p^kGywO!S-BtT#[B,@"[úorvBXMFvCYFңmG5:qLC0橛+k٢LBG5jd=VU#k>Fq#1zS~]Qk[;:OY?Pqb˅@FkP[FwDk6l«:҈J)@7f=}OhD6w^P-9j/8OL6U* 1 ]`gxjC6v6e9$ ҆| *7[*'Ԇp9&}M]k-*Bر9 Cx8}$fy( MpBG [Z@nW8BOfT邉CW ׯ iQCB$.RE)uxkTQ_ kҢ쫘#G' |gL.m]2-1 3tYNfrP1;@漓!mPjeql-sP$$ ]v K>ql..Cb1Φp:]!%@z㥫9!UujTЦ›1 7z' FI02GUb6n8ݛ!qP#HvVq &-AEAޞtS~AC:`*ԫQ(TgK1F=#P/_#Z2 V ]̫uRDkkH>@FAN\!}-򛻝[nK{5w۰q S[6QMe4"xjkzx_^b1/15S2K;0Q(=bA$|A) _3-~S :\ 7UVɥ/lwKmⒾHWcr _)4 VSVeM4D:آTHg/* xLA?v}Ě܏L}_qx#%|US0R,[6٪96e 7^i:Kq-5SW +Yw %)8* rX/B3[@&zx!RPȟ"]0]dLR=f bL˕Vq"TqֵnHEH<%;"!}+)K7@_,U/J@ѹNbI c?_Z8fFm){x ̫ORdB:;2/ow]/O|+.b%0ʤß>t03 ?M\Z| NCB0ᅝӔxѐV:|qDrrq'r6Z!@G>o aZj;t"xRK ȰAL^{]^ DUV%]S𨣪%dJXȸ3F)V,-Dv x:y p-qBשl9O--JRf) ՐI,|{],-VLebF'=e;~1V]uKրn9" &r=ԱK.JTR<%R.1gx?'>*'1 z]FrD4<}m-')q,ېU TQ+l C#!U ]7>o ]Z zsx2H،d\Fk*EiC]B癰 rGu,CZٞC~s$ZhٺcjqIcH\|Bw^ZAG"K6C_ԛdiH=Gڥ}: 3W TVCu1Ka~MopEjpi=tkqHu#3AP?u N?(﫟2Ly` cv9#r|-hN=5˂b(> q2b A kq}eaKA 5rK*ΐGe P DujSnY VOtmbQ~!H4WHnܲd}v /aҫ~OKVUyZ mC1l-^WDC=&p۱^8'[Cn$@"\<7$ Mgg9t D&AJPB `@ .MCcH*->'+RxPZzC-%#H 0E g~chXǢ%#*8yܟc;І@>!t3f=nUXzJJpӍA孷0ݠҶݭGI_VDvW+r%$6v#AnZVvcch9cm7x:njUOQN$ُKIb|oV6bؾ(FfG018 77}^07o tRol=4B˩G䅟P缾S3ډivc|td2*B8 7xHEhDд( Cl=J .n~2EdVeRxBlea-cztRUT 2҄2vR~A.GqK΃SPK) A)al9$W{iUrzTm>Q%cҖ.n0h2ȘMƜAUU3!{`k.<f=ݣd9cdym7CA35bG ̛ EJG#ooقEQ] Q<2MA=ro-EXckƧ#v7gE׋Ծc7Ou F־9۝t!ηh_TYA)'h.ַEu8R){[&%ݥc69lv".s4|ͺ-af]ԾBjٗ!n ѮaV"5*jkrsDF"}e5ڇi©F֓\ Q/NE%e{FX: >qNU QKY_rAn˪=ԦҐ\/Qeg ۩1jQm]#m81OގBF( 2si4=\aGhK5e5xR؀ < XV`V{z}cȖjdRa5=2"dXgX+isN(TUer%q[Ԣ %Bt%#dӒk`iղtթfzZW J;&]&{u׷ ҆T(Ke ݙ_Y^lScziES7Fo;6O R`%v[d8TQ9&XY%[T~c;ƥ U9vx6V&e8y\Q-](|ꏬhb 8O~O;6;lL -fcuZ~cϫe$ e%6v3y Óc{fis3޵yӾ,we/m[lG)'YZQ:?G|%YўkJ 4, DII-N^QU":(zӫA 89a+-2-f= &# tNG狀,=%cD*>>^ ?!Ln6dE|r"ca"VB=I;!Gh3~CkwB(&ZK5zo6P .ܬ1iMgm|b)b4-eXZry[ZQېV܍OD)oeϐ&p ,k {x7;JXlQ$K=7ȾmcniX_T3w)f$[V#Г d8lc : `6J;8h 9&XcyF9+|;?ڸS /:|Z1jqq4ZbC䝍R_-cF ¨r|Å;9ǒĚoMm@ٲeEB|OIDlGJ+]e ԔȈBJ` ` puw([ieU#5z*Ig@}+7|Ji[7o@%sŦ8k(WVĀK[/Խ2\&͹S*?4PexY A3D3=,-zXվMtx.)+}摊j P#=,6vt#ip MhhMYEDr VM[>^OGkMjf)X9ҙѢm;l|j5Zm_q.@Dol0'c9(`[l:pS۫~cR-G`eH7(871},؉@*ӑNxRX0M% S'2 Õ q ntFMq4ؑEg /DJ#tkLynX Ӽ+-w ;bc/z *w+^UlVcV(`[[#8|X+jF¯tй7Wv99 6f 2s mLF9@ȁ4^O~9ϼ9P,Vtڭ`v+7c~s/y ^Amj+__x1=oX__MVV?_XϗXbیՆ0&&^.og h`nR!I,y/ǡ 9OOnyͻG^w(mEy0ӲSF]eZciSXk[İ|@a.IAv:~hC*p5Ⱦ㓿&\T}_?Ͳ4Xɠ ]'x,7,IC%AfՄ.R9ilUMp'_[p%2k D`1m mvH:!"]W'#Ɓ?7 I&؃|kQ(-F8|e` \BNC"P!Z!X 1D{ n4yCs!b 2+%Lk5F$@v ZdY ۙtgڿL7F<σ| D7V'A/@bހ(94ݍ&Vg̃Lu~r OQءOvP<"Ay eJ5E5" eKqC AqRBbZH@^ @B ԐַRCIފ(lnI2*o ;E"i4{G$ huj&+9; b@ ?[IJ@N*(wKXQCtJBXcr-P|#IWҒ6#nܺ~4q{ +[bn^]o qBU]K{l&v^mWÿA)̶ϣJH1&%~x$qhP'V7y|"B[}c7תeQS6Nu:`;L$ꌃlPBVXH{KBf6Vr0KVkuqdy TnKT܂lC2Ib-,ҵ0QJe(Ad3Վ Жq.#f m깳Vxi),]$UWpSiI[!cg<rAٔX4 BΟ$AR;n[u]a솻I@%-kZ5^nn*DUUsTh4R\ZQx3_P"+$&;VEvY2"1̮#?"֔*kwS#dT`&lܨ+>ERA%TU$df”dnDl;mڎ}ф;K;}P@[!%]PEeĖ6V2B)9t]̨̠kaAɘD1Ph H%35U7ܶN4kgކV,,PE*m7 2Qfꪺ/O"TM s%_mLn[-rB?7%K֓eUA`R$ f-\}MQ~դEM⬣d5*a%:n8IdA[h>+=檃1(k<|B K~^BG@u7m/?#mL)q. ۤ+ކ4ϲq߉8;l?v3[keVdML(ݾFU"Y)fu͌!0x} :aȩ1^'v_pa.۠LTefL#f.b>j\&ꚙ4Ul/Ğ'PO.woEѶ aKc9^_ТN 1ƨ~?hϰq-,Xf_+egt0y)1aqB*)6ѴwKԄq\k_d4vF~}(S|P %(?O0 _/ @Žo$s4M0EU|筍[C2읿RFZE|,UG/svƆuJOF7;<Yσ&( _m׾qB]gR0`HϲJ]?; _}x( %j0MUtU[~Dl\~uHpHOK̸d~6O/Sպ&CLj(A'`ʐvFJ&rC&!F |*\57"fVC6kå`lu8ҡvbFj9VT/ @WOYF;A țxb1T<"6jZ$"@SΝd0$FC:EMnb/XEP1d62*GlX?D>Mq8˥ ^= oKL^3)H%+ Ad64 kC0]{X#(y:2<@Yı07zxrWa*9;&5^Cd\$ed9~߿o̐_j J_ &&,鬓5>|bHAZldBVڊˋ.o}|/ٴ}ag: $"W٘7=Nɬ"gW7ܜƬu {o\3Oiv}GB%`'h«TJo  j?;Qtt@ebN ɘ͌΢C5Y╦nj&WSY) ,eF)4nUH`g~`:CQ/#wC4`39\E!zK*JkNμޫ9qH><@]K $vAfG~0Ȣ0h6h& `1F0M}"εLȭ-ԹF63[mlQʭȭ0$US5{qqHCvuKs3b, |8F+:@zV 44Z ԾfmL KeY^mlK66W u yg^ JOuG)#ڂP0`.ڰ4(@Ǎв `1&Wy_g+0@x7Y;n;ionfj9_j8nHSimXãRm@2WKj5`y(yRKhuֲ~"mr%C0Hu5d6<&͟)X`iK|ܽ}|-IUHdLV-*s5(ڕg˱VNJHT;kA-$2#t2.VӿVj߽%jw iCsV4@=1OPMۅL:%KsoyQJINlxpﶮ{da!{]Ӣ@3EPd- PEo'-"{1񇅪ӹ6Vqv;*G* D"FύpXe|* A42HϚb2]6$HǫT:rhaa,{fDABUn6f[| VGXVA<)/sXH-qd߲9C- y6Ϸ2k:e44K?  }$OÌPd@ p|lhf:cӲm ؄).T1qd@E}r~M?ŞΖcno#=h9L7ң\0mF3;FTQHk?խlBh4D"1-.8XiB'ҩ`}, YH&1ԐӣHAl҄ڂFxaQHF隉 [6J_8Yr5K<1eY:D̷W9 zmU^,C/A(2`Zhy6T=֘~aٔ֊ 4U M+Ҁ-eJ<֔aϊZpr>iEm$X c/\ɱϿcCWA~_}]=¬ifLbd*>n,{l; [/ 3L\8!'3&9:2Vm,/$E4 `x(&e@^a$-6iOQ)z?FblS)SjBWefN4bQZ[@Z"fٲ@R%F\:Eܜ)Aкh;\T9UNwrR " UZy[ VsL(\4 Hӱk{ ºݡV0P9vklH3L^|V,i\sSBPX(h_i^Kea"f4Aۍ[o%& ]ǂ},tq3URgs6c\WqL -NCѹ Mottb=Kyf"JIE7*TTRfaG.v2DZ O4H|E&Q=5FYU5x' r+٪䣣#E+CY6ٚ^)i'eָ֒YlUOfkB ˖)lefNLC tHm֖j}Y߄3񟜙riڬQfkѕY)p,$ !2kIgٚЮf͡_p-Yߞ>F"qnFJæ谒eq XFe/שzBs2}שVi[qj /}s A@36h"Vp޲bmX*sH*04!}u7ܖ>ٸvF> +OT2l*-IQUgSx,^x&),LZ]'XhfG[̕ۆVZ] !*Pea5%ҵՁK1To6[?2ΙF)HRM OJ >:x* ofavDf*LA͵Ђe1wq8WQ1 lfo5u,> ABO C%}\BA Y9(>Z~QFs߁8Ae )f]wgCoWHM,UF36jP 毧\]%8dvz> /&eV%sڠ욤 ]df5Q|qMxuR!lա* )>@3(s߮$Sdd W2 KhTh}%CF|U&r5Br7ZU!vfDؒ!el{p0 UtˍƑ;b:ߖ,\hh)T>rٸҶ }AP^+6\)eKm}U@ 13|hMͤ܉֚7#4wyњyE U=㌨Ug HЮEcmol1W_נȍ0FáҊP|n9\+${ƒ@KG[lXhcyt@n4ďp)&;Ar ɍqGRkx[,5v Tŗ)kR=F"O͐]~Ϋ$dWi3KZ*J@9]eeNn,i6KҐJ+Bfj ~bHzǐb3bH19YbҋlMD`=Xu^Qw~CS(sDQ˹}pR{'38WNW-Soo.pR# Av̈'V:Ѥ!&_ѤbT Q;r_DP@ (RL*GP;}aOPiQz؉MN.Jm(>>4J^Az1Ko*x^i=VR`7KW 3nGw`8hqUXa^+Er96I'/s /@x">;%߀}agil o _QY>h,mӄ!٩a!۩da㘇؄7OOjx`莜N-V ߰)F8K>};&ֳnC=nrXVMb f %gYGXB|KTd\,Ox-7KزG0fKV&9G].8>*Wv8v)KA` Ws<-6Zl'6C<zC'|% 'X_>_cIpkjN5RSRP L*l8UiEg`oP q#%KX:)JjʁD"Q•xO a){栳ߐiM8pCË ̨-g$8rU6\&YLkRIc[T#ʅkA=-*RΜ<ge!Ʌ+B"T2eJިp2d⊨{foCN+dL#2 b)3:OiiJNw؉%"$Q;,.AiLܣ Qo Fh2S,Xj~A7B.miOBN_T2'Á}Ó i?iPL GĬJ6/ORtV/[ l{XXq {@#O @D/s<(-RNh82,S<;!Ze>E]AH *&y10IE/%!Z'HREsZV|J0\ikC|"B2:|#092J ZmEL -9uE./EOs3SGbR/s!lzςbjf'%wpy0b4"(>|L/Rh<SoKG꼇[Rq*- :&fnY=uzg3zW Y#6 pz<:mbt1~r1XC4=Td k;WNS3@(n+\-+a5J t PaJeTF%[f:y}bheO_;nac HC KZJ/;,[[+:l%7% WBUmYEmɱ,|QXd<7|Ň8CÖSƛ158nzBͰ,}xz;ٸz~I[ir D#(1H,<J @8o7Ps!D=`F3ѭ|AAf~3b=^Q3+N $!2[̿*\2oTj"8Ji<Jq{Q*u CT Ṫi _Izd{B\+Y7 HቃFQ?$=zItێ:T)΃`y\V@<2v; W+gB(4 >NSz:e:+.ظ:K:6~q[G7i2:=k<Y{:x:7g s^\9um:MM봩^,ię۱l$B0؎h .Tsw nl%%V`:d:E͂[W} tu~c:m)fb:4dFh]eaϕu Z#}+󡉅|J ^5x2\W [#2 dy->H6n2y3܇CQxb !RFA,G#]]Ejn/5v,C"WcE,vSP Gj4qG"=2xA2SyBbeDAs >!d V$޷éQ?!م+A"FeY^f޸c9އwՅM&c?!C)7SmwVI(ELq\ 9i`x&a@b $/Vu0YRgqjBi5% yw޴E0fh<[".29)F*)8^'Yxp$,[5V>8r!),},`--0sh&`EއHYVԸxˆc254VR<тT>g3TNiXPርuPۘ ֿÊ'Lu”0Aۜ.TPVWc>@,NmJh'CAo=u}*^S` Ppp-:-7I d^$j2SiӡU) "y,/ǃ!#B!rgAu$v VNZVFG]8Q{!N PZס~_@08D|aĕ)Lॸ4E+ 6^a0i0,ty죽-I  ŀ!0x|O(aDVTJnw3 Q7r e탚K2#܏оÐXzOj<3h1QBD@QID.xI^_ *rLT[o&lnШ=wxC()ԝ7 JN0 .IY<6EjsB\si8KR-inP uN)%^> PWPzP 3Z JVk$ k=^X'X_?C=ğte2 l8WLՂ6+,m鿱^dc3~#G*Ό)d1D5FǠ9;a].2uҠ}$d$_Tіkl7l0ISMޖښYm٧71=B"uad ژZ%>kAs[݉N6j6T*u )ڼOiL-,R ,1t(ûf 5 +BQ*߉ɲcx"V#$`/+'Jƕ!ҝ#J6 z NVF(eLEns|IԹlN^g܈zhYyF[ ڢptb8,?UK2BGXldE\XGӴl蛇T/ʆLD$ʦ0n3_ݛ,Vv\fe><Ǭ68VrE[+>bfysvU!S[A8/VE1JXK4XLjK]1hcJc,|EXpU4F@2-q p l@$N˫1rEcVT/) pE¯Bۡ6{ʔi;+KLAc}PQ,3_ 7 %S#AuvU0-9\3qhs.|9~Dg&n ΖZ 㸝K]s![g܉ܬ#Mbn !)v-xW`\183g#\ ;%¢!Yo|es|'C fs{ c}'t`?_G֧#}j}8fk"RC+.Ԙl=ygl?4_h!ۡ07nN.񣸝&7W{JkNj{edsD%ws!OHN0ZۃY/ۋOCN/2R0B܊@W ?tZ!.?32G?Ў}0gz:ۛ)ZzKtCؐ՘ B:Ė|-3N"6SVElQ5v!y$yʍ\BʕY5&1n 8l˵yܖ}}nP$µ{r!\gHWD$=͎܊]J`ϺʡrPVEkk#߀(( IJpj^C5+ g63,N(TD,lu} α(+B΋y>QT?\iњ]Fܑ`t|#j:\]zriT\}oV\]J@AW}"KDe6[`+9dxa6Z&PF1h:oF.P^c_n=SPHL3[XM dtbX< +Cpb&ٸ%IR[VI?y6|>⬂ݹ#rD#Y^U w~C! S@^Kk8RCx $ba諂8Haavc76y$:4 m,B״1)'SṶ̆4D! #%ja1L߃Ӝ5 ŇbN~ĕP{Aܙmhjve:XqmHTf*\s`]T6&cg蚃]&T '8Eސ3hZ2Hu{?. XB*~ ɿ~ץ zh6ITT7T+h$&+dք5Ѹ`7Keuuz$W/f)0}@2YhՃljAhVت]ш.%(ːTܥh0Sc~-dMHϟxҬ9y{37T|A-%LNGsM Akqh Bá4]zA_J r;i Bk#4HClAt#}e٤ҝ46%C?J%C]'MV NNg~~^c㿮XVUE~)E@\7I@ɐWPc#v;fiNҗCéR`Y'HQ̕r`! k RXSO% w*nVIu)3vROK(qiӢxWѢ"]FY.mxvomNgW7Cncm\!P>OQ>†\cK;4.A/H]ٸ807n[xhc7^-ko ÏZ%I"EssXsX!ˬ;52Iu ْpxG~ɗ#Vq `^2e7 R7af!îZ1=cR+q]͹W+(ؒ,ٓC/o\4 s >@ԟdزE9L٦e*&T4W/F,!8Ppn .^} :SeBtPs,iʟ]SU"65#Ț>:&R}mjv?Ue74ŰR/]j'n|v*v 6Xwʸ"i(v9~&6͆PP' Lpt<nO̴!\va2Lm(Vms[vSYy Bn XwL(yR:8z~.HM8"@$ä1yf dݦiK0wc)UҤayUW r"%œZ22CASa6A|ک#l59?邁XZ &ڧ0Kp~l* bB- ku4мqJW&%T)u\Y|2,!ƻ.zĕCEa-3$^,"d_5F,Rnb,^NR.>q/p9]ejNQDt\T +4 PW#1wW>&B̽Tt(~f}ؽrrU\UC#JkRլkG< d©¥SWbrP]\TƔrrSʍRV!"\0ڲ7G].CŌ.SW_K#sBBWm8$~({sAG}Bqu >&~"d9j[,x.߄+W(?b~+fy#LLgAl՘a=*Kz0:;\2KǮ0b=:lj7p| t*Sf XWm/ni"Uf9)SQ#.UƕCeBo%y# *@"ϷtpҕLo~[ l'uPa^)5 4K 3׎Vktb^ͪv+a"F)joJxTsNsrDꮏ'gЈINF/}}6<7M<ĵ_\frwQ5|t`fKȯO:'%g֥֮v%z"vo?jk/tN]Geq¾R7jPTqEP]JBMl!`cw^oD<*U;RdoT]9Rbjn^e[Ș'ps5|2,+3ٕ]i.Wq\aORy9RTq،j63KRߙUuv 8#U]ts9AjdR\ 9S%6mYxSa b{d&DSo-R;ih% +*12V>rt'`̩ZkY\Oܰ훘)׸Gdw.4ҜY%ǤW(FGTΛ\ A:bk#֡]TĞ9qs |+((R֓C1|3JyN⹷S᪊RjVbVBm"F0u^a/rvL\CF^9HXϒ+5:]YilC~j;$S q.5js!4'RȠ-U9?z+e&VC+zZQA\F8)6&y$>-_kOGNr@`@\ 12j&aV%1c-媐^>zk|;J"Yzѐ7(Jφqc6}9ۛA+֧Q=+p>%eD Ioeuj BTI{wLE?!J' HF+|^e Q|.xV,^|~ۋloy ʼ8wy׽< `!~h~tP._#N4`TV%k>2@mĩIHubvm/)TE#Nz/rhL4V]5̈=zKcwR߀؝bjy&X?bA&dCLf;| ,ɊJi'+& >Y7 thp+'un+BG+’hdEV'>trMjO}ޗ+uɺs˩$Jie*-OYsR|l deG'+l5X*kMu}'jY}޶̓:}dً[tf{Dh8sʬO#)c=60wMzdJt~$*v_v:u8jOxX bDq/n{K^rT1%`{Pyۻycn LT>Oao9[М˕Jsq63B`Bi ;>CL W".S/?GIy(t-&`{uyX^#Ծ}f뷲J3a9[nȒ-|n/wI\2Ff喸Afz©|LsVt 3ݹ?V5ZT P]71,{=UӆDpCVvEՂ'8OFO hFm]z\/} ,w$j܄u,5Cϫ6 RRwR.X~5ʞzmNK<&QWS.g4jD/> `l %^Q@hA$BF{iC'}*KX(· ;$MRHpn{~$rHuA|$WRljo2 ʹtD]/bΑќf@#>< t{89+eʡلU5rE "JV7 TVsI4r, ,\&i4@P<[$xR}Dhx/}^֞wl+Ƨ,:53#8z)erxy!˱g{UH`PDG%bߚ *|{-(7f )SrN&w?9|0TͯdvdW;obuk̛'4-7Z:5aU\d٬D)oVoNQąobRD/i fsՍ8cyDI9`u8kZ~U[tkpvebWSVkbp 7+G-!>O*7 Hvs8cKBhYD,x `wqQE#veەtP([Uά Ũ|&slԜPQD;pS&;o  C VVm#*Xݗ_fZmʮhﯨsE"(  \|QIj/d4kvPffצ'jFlhڧMhfnk;;J.w7E=f6s #z[9oImܫHlS8 DM +tVcP:І*JI/ Ҷ]9UۖNuNKqHŌUg [:kM94]iGOCgO?>Ψ_(C=^qF?u7ө<\p`f?`QlYj(e_%v;f9p2h=Jnk 8(!$_t\=T9}JQ75!m D7 | 5P|ʙy[4K%YoyB +\ƃ / VFbPm|b.ds4VTU w#' w՗M <Z? N=-YA=XO\oJI\VpvTQ+d s<ռ 9ZM WW/nmz졔9kmC'^.Wn[@:v?MG!OX$)b_,}K,>\.*ĹavN\Ww#?1Lc 2i@LibAig//ӵ%z|06{ͯt[4cXXRgУf{x]iNs=ʸ'??W4] Z<ؿ|ꏏZ]v/'?~fu0ɣBئ=|?|̕~& 7m&3N8Mq|@o67]|ɬ&{hӡxw@_&F*o-TG'1KK#hl8|7;Nv :J+ё(Tmd)Ol!5YI2Ήp'֖Gc5+1R :WpS[J;D7ye<,}97̷@#|AWxx{|bЇsh@n88A (?$JA T9b3q-#୷eās쥓s=+CѼ&)JUD>TAKPtJ32^bv%–gH?z(2ɢDtQd|RLUqq\Zu<9"]bnDG&(;tm?š:VW"åG) ~-f]P~;tstK} DZ ?ydb6z#w6Q2bْþ.^/ .U#+DW| ~,BӏI{51J,>{Xư ̋Gvb]i*Y$[V,ڨ b5+;S3`WpW>rcfr%:v*Hw[+"FsӘZ]z˃$g fwN>$!N01/a- b us aGrj/t\!@J.j$g*{9F@"H:]G3 ܣ\2p 03@M(H U4̑$Sͱ ̅銯 UnޖhDښiG9Xo|jD>؇dց9o$wՐr 8_.kl_ q*u?_CU;qtUf;pݖ#R 2`๢4YUow-C./횩p ^i f_)Y!wjl`qr3Jb8hJ {8@\uc~&PlF.E벸Jq({szHr$QC҉{ZSǑqCP~ݣ^3n]@R^C>=XsӼ7ǩ8ϵ5%9I=#G:g"y˵FnP݊&<8rq` i/; ]O_yMy^ȋ@~JEVe&#;~,B%R|m'񲱇S8aͭȭgW:&؃7oؑpKOj^QǞy䤈a&UG=[& /Qr 8dCT X)xs#_s\Ĩp_m%Ƃ p$gq5I?Ju:ەJ$\CN={0BeV&~Yt_&*_A8Q T؆\=mTv j? O[ ?"[ 5a`9p\CZTQg* l5ê6%B%1Ejw酆Kٍ݌`2{7Lq2Q3ΝV#\2Iv.v16>b{0ym?Z =Gްi+۩Ow;F6H_39GtGB7vů䃥gR7 kyuNG#%oq_.*t$(6#eHoRbJs^QKl ZD\K{i 띩+ݗT׶r ^[tPLoz0!_Vfd5enMCIQ@>d=zJwg;69 /7HkgdNq{88Z{`^\>]<_Bm֯ܳY˼7M쁇 `?[D%HX@ҳTt.Lo]^VʽҬJe(\7ɔIy{`N{Wkh.8AOA[Y,3xrqh(5l\ F_&~z#1!z\.[*Fio5ۊ{}{f+,1Rk]5D2 R WUؖYHќTre5_R ShPCt[X6&j;[y7$A&&IEߘ:20)pOƒ3>EɔI_k0[w1JSfilIMl-t&6ҎJlII^ ڰ?H3$4#LIӾAMI@{Z99c.ۙ$an܂0Йgk|qz[!8Ң ve4&K d &]'伓ҧ7t<&)NKv_yky!3yGC`&hH>a3j&ߘ)r7!yn9'{N]Gr3z73M ᭻toV=?o&8Xqt. g݀LI8Yslx3Ԋdכu79fleb;#)Hj׫?ҭZy,l_stF^OYl^W'~'<-(7f$7]Aӏ˯d3"MK56_\QYCw|J#5]vۣ<]q)E[ο@1V=9ã7=q gwN1t@H&<V /Np08²qyneDx̡!ιT$)uןsMG@  ܀UgOo!e BQU!Ys(ASUmRo .SމZ&81{f:զ*K{Xtc[ʗcakyxUz pC╈m(oc)U#=+ZspVvs5J@Dsbdw 6PsDA;}ʠ[Ub aY̹7vr>"Y4`ag9 ߎ[ɼD5驥fb[5j{<tO@4YD6YdM|صidV.ws f[#o٬p|!{NqY!f1~#vѷ<2=]:`lK?ei. x2/TWLw.Kls_r]G|C9d+6N*ޜY罚/C,d[AlAI$&Ԩj.b7 1Te mdPϑ[d`xA m?K_e9GJz-K_U0Y+?ǔKoS'ݜ put^xNI t,щ6{ziE(.P%@ݐDlb\N8> w>poDsR{Ppjj>ʳSG):e)7Vʎݏk,QkT*xko\"9K^Ź^&fw~^ŵ"33_^|ܥau?Z墅lDή~e u8.pUޠM9sȩ֋9&3UHOu՜2˒ zN_0L׏w;?<*>5gy\l3]5|%^{\O|!=~kTE>YL2Q#ޅ@nB&MxtGNr"sL_W*ܑK2.ٮjJp0!e[F ɼwS7 (c5ڊ2XD)=ic:LxۥwY ZODU*9Gɭ8令?OIĔR{5Ux]:bI7܀D/]NXcU"ba2*3tco_@#nBHz9?ܑQN Uw_PH1UO\&D\=bNŗg0?=[C*&|R ;,M0wY.h39/@Џ,_~8v_ڕI\>WPMuNҏZ؞s":^'2oe+XĚoN-0JcցH 9Q(UN&KJ&t:w#&v~8էU/`m "-mWA} E>ivg.>,r&\@P@]QXӂyK0ds^GZG 'siazf/-9 'ugw^LBNzLr noLQ4+ c2,iK'3+4=D''7PyeP5)ޯس nRdܕL2̨GdW`d^NR8~}ġh=kuyDu+тslٍ3vl2` rk\oXFBnCs)V j1L%ۋbZދTLOpB>ykwL> LY!5~eB!W]TanZT3¢y-81%U8Q54P*r"C~@ѠqJ,q4 vp-DwrXNfY~c[<`~!8O]iB2b!HuӢNX0R00,࡛hGf3ECoef"`y@oCID󵫟{4" RP5 4J${-gF nyoG^ ؆c2L7苘&IoK&svpI*- %.-ޣA mBR9ԯ1yqm,#5OZ "e58 \$x'܃-rO53&٣/AWG΃dA i}kSaT;#eauCRj#/J;7w8 9"]G.[KifdŞ5-xfeםJ:Ceիbfse!÷NP|Iy]fӇvcqme]do2 }#Xx?7x9wfByxcN7|-O61y~4wLXS`VX{:^\{˚hCo_2AUgE{D`mʓ0Cc+l*s\\U 3Yusmw>v*'H|Eu=㼔N'<͏p(Hiyځ9.T"v\35nT' ʖU- mhE|$2q!$([UFMd> (/aĦߗ^"ˈyKrXtgG~c rZlLĜ*Jl @,6H ݭ̀/jW*RqԦj.'yZV9bԡ0'|}+lI/#^ȪJx9״i8]DMVY!. V&n'МA`U6W6&bNDBQ"*$JITW!&J!s8UŞH8E.] ^*uYDzKOTzkW6Q'caxŵ3|eNwS ]hQS(m71<íjn\l I+}E<ʮ|`:\kÆ!aPW ]z3vL ,s>chqS_@0/Sξ }ѭgG#/192!]cØ'flG)E?/"^1t)-_P׉i|#uJ)VHTNQe%RU06eܚp,D$Hœ Xf˺u V.T rgEAŭ*eӈkKDmwT%2 >(Pc qDOIp9Rr_ AM=̌*\"h#VB\_M~B*8 |E^"n=3ͼޭx>iSZEʊ,i;,J|KF.3̃Ȕ(ӏV< iVO"$" ):2o鏱rv6{Wh'f| 2Vb.ݙof6Ē73X6O%c*Jq#5Q; T]O\!@0 m˙sF ڜ\9#kuX֦|cy[˞hqmWۘ;l-.ۅ#1νFIYvXV (X,?3}*Y`E![$܎إɎty8GSU[t%ȳ|ש s5*OL,ۯ|iN#_0 cO#;'<U2Rl{%V|Rn%=Bqܢ aHNϘׂ9ua#Q곬uO.VE7NФ`h j]?FpQ.X9?#Hq,.՚X,:3:":PvY# 2hv_Y;o]Wj&\&c(]6s:0`g\Da6LvJ =kgbY~0%^;_ uW=,N3O7 +RnJ UboW0?SfGWbAS]Xeb:,$/3\Fg3nWF2cc̕ZTfvpgF⸗\ׄk A\quf7Ai&v7zTC=:n>DDVP ;|ÍP~@ UoBC\WCNՎO'+4&溭fB#H<}`]N hB%+Wœaq23PAO5%TS3ؔ/)%C;[ [X}d0Qz\ 0+lx(uYˤ*.>@H'&ex*U/k9j LxL#I\}LLu!8bWV @0[6=$6[`klFyiVkDS0K[;Vl 2@#p6iT5vb k[K*#4ʪFg29s5vNmH.Ȝ5$9vc&hDW:v %9sv+B6le؅BMp9Ms!c gEa^™9lT JmUDzpHh-v@/ ꘶m; |>X5^ 07 Ag8cu|-܎ky䦣LS]-PL$"0)9T~vT4{djڸ[:Rr$P-5^Va@&nIn`#uYV6Qѷqאpk9+Ivns.y\ޔwJ)҈g} ϪG t^?ӹ(`*5OLd7gOs%dcs_>//y6ˬ͞8R3 0C-g0B<pu}+%&?J L|(ķL^-oD9=Ž2Dd#|a;8h.X &z/Z p>o@uJRULPy^јbзrmpOvg r0Jn񳆂̡>O3z:/o\?\aQ"hJ4+hޠ${Zgsso.޽e(#DD$W L|$RUv'(Ɍ>II"zC9Fæ& C5upF4}@`}xvfo(5W)PR$[z.۞Q;Aϝeףk]'qL"5 FI/$ U%wVG4WfYκ'-]%RƖ1`*-8.&.ޒUK3h ѵ^DPYkzɲKÌZ|,|z\E@D*d 7@%ASyʗ% bTLj^o7瓛$ }hw7_RXV XI.,EIŽ&IgbQ_f`˥d^9I `?xY,n:Z0advdd;.C:- 9JK׸ߕ/jQGa"ZWCuʑG boc}ȐR }zHf905J[\[1SRQP]{:Gg  qHFL"ah5=C8A)> >> /Font << /f-0-0 5 0 R /f-1-0 6 0 R >> >> endobj 7 0 obj << /Type /Page /Parent 1 0 R /MediaBox [ 0 0 500.204437 358.225952 ] /Contents 3 0 R /Group << /Type /Group /S /Transparency /CS /DeviceRGB >> /Resources 2 0 R >> endobj 8 0 obj << /Length 9 0 R /Filter /FlateDecode /Length1 1716 /Length2 16411 /Length3 0 >> stream x|ste߶-vvb۩*m۶Tl۶mۨNmG1c7)-#w4+CJl`a?/BPJXWv4lY31Oww4rPr054P4v7nq356qPPTa{Sc+׍?;q 5g?(Ll~ )2G63Ǖ=1s+kg+622Wc6?Lm % ZܿX`h 0t7gweWu k`oZDM-Lml%?Hϐ E-,u6Mi?~ɺKT52J%t235u147u7/ae`hgaje(omoK@&V6qV z+}kS+c+@NːL_bA2t,鬬l<v0<F ;е7O@/@o' "З_ @W@|-v3/iWg7s5kW%VEW6/dU&~ut::_eLghb|~wWG pN-5\pyUf\=AO# c`?Uw~kvSeNZu9AsN)Þ(e E 3 cm~{cS/kBzQ;w7]b4IwIŖK\n*>Mՠ߫Q9܁HjpNz`tV{}TXu^wh Z,r>a4ȡ&|Xww/R^;D_ J2US-U}_{Iae"jBTMEg$c$m޽ d {H2*)2ܾ0xApPMBCOH6vo3l 9KwMav+'*>[iR#-xl{R4 ]T=]Ė4ݾS Oo?o&6_\{HMe?/F\H(fL$Ԃ{=gzDwivkl?Dn|Z7Xvf_~j|'W'wP-_$cs#dm"Aͭ"^sH6C>@e17* "ŜWp5Y]8JެP T|W 'dM7&rMк*RAy#E0{$ָB%cktVbd G :my ؗ Fe?\Z}UP&ys=)*G ;7Ksn <'qSFAU<;fJs)^_4P3`MX96pWp5ӘF3I^y]@=6Xkgwm C$V}95}s X8HP /K"_{yޖV1f@/ەL +R5s>Y!OG ر^0` % u~GSVI;W3u]XJF'Dpg~s>!9,/ `cQ".[N z`J٨usyj޼{[KG,m [Ǘ(ktr9yS<.HTJXE vbWC[''g@M2F,+Cfb3!5{P{G4yM8 2İr`Bv.b$>K07pRlCݥ'JqZ"P=CA{y8Dl_WàU 'M_ #w_n&"LD 'c"kR&8߂߶OsT P6/p|/Z5WNmJ26?`Zuӑ+\?޴KX#ĵ<ivP,0,Cxdp;#SJЪS6|vdW>*"8޾.e&Xz=z²74sJN&vu2ǽD7fQ gs2d > fMqeac]ce}w*3™I/jno;7ݝ7cz;Xު&Ͻ;*,r*19SMs1# ܃b9?G.NTnIc'.Bzp kc maDlI`\~:G[xeS|O]y2 |9m,)GpAr;S?nkDj4ᇲ2DؖIWNl&"FaK_b[PeMF.K Afχ|`cQ-*_>5R#I7">Қ(¹Mc(]x/‘@},j?}t%UJdQEl~ӋJJtbSNq)X|Bs54׳?l 0b6-8G+˝i((buK6G^Q!|DƠ$D .lͧ]@$5y,r?HX?y*p j}:@U=hFÇ{d]ְRX@y岼IT}~_ QO7,CHUcjQqy^m 0$tv,31i|$$)Į`,VO; rLhx{UYY.IJZ5ï\M&z?Y`չE3T )u]by6lzbn\7ZE—_UP% L u%Inj"°~ )EfH{vm7(yFH{u"7fMW΁)x5_HW2i[:ۿLvtjI#u9GZ7C6l.&7'q.\8C1<Ϧui0)@K4 2x DRzA3D]'6V?- CeXyE(ʦAqK <ܟhs-1m)1sV{GtP8 U ΒNCgňBe[xRik˨Qd4׏'HQv~xso,7#Lݷ)W7{:ZVauX7[` X̿ _?zdwpT?"R&2ry$d&Բ3vV]p<P a@bs%ތeI|?8M$fl9݈,ЂZ$1^4G;`*ek?6bC$$feuNSnN$Ҧ1$=#}'ͧ;{66fLgZ2t,|iaT7 GLLiKΒ&hי|/x h™I6, FWUVed# "3t"խDPϕ`@gNklJ%Dj ȼy)ɭ@xXT(^})S(ɃWhAjH3p Lx QjjmPk̈́n,t~D y, ĤF9{8l;)Ϙ7{ch@9BM`~= p@le ]B;pIE%?K=vGrCvc֒Tf] ?Oy1i(,4w604CLw/LWèdҔJJa. j"F^ ig[8PݼCDDz*k@׊>v]UsJu&'Sej OLmi1N%g_BEW2fv?;VDaWzum-yҎ^gy:SփZPXbYp÷qx IkЗF^%h*!C1,@6YXߗڍ;V%`@͡m68LT=GP>]@dB è\S $L3bΪZ HC+]됋u& |FgAc[ݽ}YMGcIS*A W.=M֣Nc,;oL1ndnY'nc>IOgjG)M-T87A9N=WQ0*2'cDC>yeB02{ ̑@B9gIw /]2Y5ݡ1~Qz&sѳb2<2?og)0A4eoc4=~y! 6)2r<4FH( !~6/M4Rʮ 2V#n3p'@Di:Z( %"x:-ru&<Q9R4Q=i= ZuqoGL} ;Vl%*>ߩZMNI^ڊ,+mĸS3Tb+500U Y ]O!PoNfgq-| 0y .Ǚ/V+@ȳs0#J:|LcR>M5 ehB |Zr`GU6mT͹$ebe[ =/;,Ĕ&*6qٗ_$èFcx8<[#18r+BեF I?a8pХ҆o%2sW֟G(L>ei3+I5d{&DEm@j3'?IUVl2YUM?&}C]׫j/gLu[FjG 6%~DvEg8T, o}FQ,\,.]hf49cpl~b3ɻ/>g~SqE,9.{’(ra(. [ӯrw9\jq\J6 _-dO5-ul6P-GV[Jud!ZER*ؚƣNI\`;%wi7dV?t fGm/7Hv1KIt 1S7oY#1:⯢[,C}Fz9Ĉ5fk85#oa]j!'I:/67))=YѺ.emi!1q%rT{1/KzJ!zUj뿫V)&LK@V% ]5dY I5VʶV/Hk]0jioUtg,ҬIEz !aR:~w,2t.穵XUqu9sI=YdmxƁKaY![-8/c5

fz};.ɡpdk%cpPHuc3xAr@j_-~OUtzS?F{C+4alx`%N>̟2JSOXfq=$ۂ*zTM`b[uN $egnΫZ|ե$S'PiMꖬ+69ެg2" KޛpXy6еLO@`G+ ug=*D4ڭw}աfn+ t0S+$e:իĚc(JTx8]%P5o( ph Ǎ"ňmcA+Y*+E7B,e]vLLHzj\u<['q5 =(/ <'sBTvrx&mѓ"* F~N'ځL=#҃-Uo5m|MQ@ MD+Ez+EKčGhp=j& U]kҳ[śҲ;43bu}H"cQsNCXN1Kr`dxdnhbӇݿ{ /PK{`qμ㽊V0f>Xg#F]H"EKz(v#bKKSq RuX5u*:7Ze82nZXԗ=}]!GuޞQ/{fȞF?<Ԇp!#DŽ5U.!=N L1ve&3Eʈ ?xXU.i°Ε]mJ,KVp=XYD;oϴx?FS4rZZȣ3YЈ+@vPm b{z_*Hu3 _c&( N@hvgⵥ>fRa(c-N.^q:} eX0tׂaxx"a^8Xf> -6SUȆ8m@sq,1Q_yDa) C{Wb9mB iW .̥ =3w:ueJ299e]3!uKxi+Z!dBuZ4 ,`l~"^Dg 䦣iD:EMIL,f (.uAի%/lm}"ЫSiGexzL`WvIR8#~ }j} )5d^![Mí߮>G뭻󬎵RF\Dk}&誄H%\2h' U{(OMKT1+4ˌ.r FI\ ˯㜰'6;6fnfH,O| ފ7D H'SCoXzln8 46s"´NQ S@~/}mHiO*JjH7sA|q KXߤpz÷[u@2$Q*+X1clj0 ^. T9V:!A_lAl5BGGY { fMHL2Yr59vU5, ⍰? }BqW!.-Tߋzl6cQۊ@ d1vQ vC,Šz} ա=igtjބ1&PW]{*0oífu 9qqaxEb2=x$;_jm]_::ȒpM=-_ocvv(fۇ<Ɨq"SIwT 4V2B 瑅O< 1 bhK[}LYq3ߢoJr]D6-(?w"sՒ10QH' 75ƨgrwBΰ6m$)r.!ό<9ZppY$I_/*%-QD6 |(d|Dކr˴V~OOY`$YW:*9Tdu/HU$S FO\߽|\w~K| .\(9߻2 c+^.N5qrsۼ$Zـ&h|TGdR "{=}W"_:PKS^ 3îm¶#=o7 [D'T}6W:&_IaQV|xDm#s͆mN }7+3H+mɎ(ۀXXֳWvb*3ͯm|(rZ iZEeoxhy7%]~codʼ/3[*2paCi|IK6^TݞZzM ˜J.h vq5Zq$sHSS&ZF3D:i%q0@~2(J1.V@u61X?&ߋMCa6$pөX7_ϯ]juH0Ӎ'6&KR ξ}^w\XT| zLh 4C ì}7Sے TJQ9CI9Dh}'i4n[|g'PKޡ+2|xMs!Rx:~DD0[Wk'jNg͖6 Q&Ċu)#PyfU4; 7op6pVK 꽴T_*V<6Օ[PZaK ʓN8- KM ] hټ-p Y?%vJlj` ss@)ec,ʟmfG2d΀lOZ+1(gZl%*՝q%*.oo֍-dR^__£Q7oG\},=Da7+ڭ Qj {a'U J0IYҝU@qFX:fTy{ 3Z渜 6\zhp`ca̱$sS.'S9٤]YRpr2Z}9] 촷^ }1 b5 C$ŗe7)$[@j\!]MM9lM +g,U!_ֲq /mv\U]#EY5CTk16Y cZp@w6';(HR'< `i |DTDPl5c"Ut "'\sCVd iGd:Gt-12sӽb"P"t#}/l~rԡ^I.,YtD k(6~XTI j*睴Ɯgcٗ moG8WT: Šb𯘞nHɇyxgC?J#)nʿvwe:(+'"wRM -mFP7FB>`lK"!#z?gp;4θ d2qY OzRKƑ4X֘DBe0JWM7,.YeI~O}lW3TTOPKl' |%YL,~UXYeKݴv3:\7t&hIcj558z{~VєظIO:]utM2f{/BI!U̚ow =u뢟PFF/ qGzz!>jC'j1.i@,;)3c"Z!%B.aPERšW(,^ZwRv"c7XóFO@Ab QvG [5CǠQj5ИwpҥXWz8(1m 3d"dpA -4&(5!n{gfT1 !7Di#Y_i &nLiN3 J>%3J"AUUoH%|WyY<,=g$e}Te*q?S+}k@JS)3 #`BT9,iUFr /8DjaFdmI@N%4um%13ݾ8jToh7O"1U[#ر;iWwv8df ;uPt-PyUm g{qM)*lF2XY[XІ̂%t!#%Paw|tq$>Ħn."=\J*{.2mIN % 7E1N,+UFW3+|| 7$u[gXf PvK茔Lkk57 pFGk! 4/5e?` hXf3\q ԨiB,%<ɟN[ftlk2ڸ;;cI dGכmGp+YDGHm/f-BdF dMEhS" } aAOIn*sj<'s{^b~cJ G!qE7ѯA,!w KyԹȷKgZ$[~PbNΧТ&Ƴu8̦$ IS5r ŸW.L0AP3" $A27.kOWf8~h0=ϑyѬb55juY}'Z07 4Дi00BЩ$~v ?:;yS37Yg{W:L1@tF6\?~bmZ?8$QuLQĂaQQȉBJI+¤txys=쪂P~9ŲF6(;PGMzTW0\6ӟm6=)ʅ ط/{׆4n_ HJm>[7HcmD"鬮+|Zߎ#|+z5>rP4dN1uiPRN3M ߵ7T8T|L5} \$ɂ4,E=VV4%M.~mf{h+5hn:"u0g/IZaW>YAy}xU9ktKV1+9A;zh9 Xc5Fʥm~2;a@el U{H,:'y\mse-* xݎ$CB%=m/*z&mPrxc,)} (sQESDn\m5w?mCONyg?GY1 7i%iUoWP/(C^㮯V 8n]]nJ~Ps-Dd3D'VfdϠ*G^Z A&ٮ4ؚ ?r"Z™'9Haӧ ˈhk:_fXSt.:9oˇ0Ԟ(43f)t!q 0 xd1 rz*ouhF@fH}Uj\ $KԲ4Z+="F }ykǯ9C_[WFwҐC4^A|T I EU]ZEJ#}(bq`0כ` 5=Z0 G!>?<7 h4~=a]-nؖ3QR$΢QbOʊNɱVm0\/؄\,DYㇴ$Yz1I[tIٚul`z}lSQ6BAȁ.7iC>2}ؔˬ+P9PqXQv>Vj^^a1S)[ve{2*sxj4AqqV 4rU!9Y ϐN2P~,r,0>XiO)!gOu[ot>P {pGlER+3 >E dZ|NjZ.c0 F@ƬM]#m?>!@^$Ү-xE(˺Q=}A^+7'h#`zF0[g^G뢠E/ݔe ů= h;/Pa=<yEP*8߱Ys ɐ# endstream endobj 9 0 obj 17475 endobj 10 0 obj << /Length 11 0 R /Filter /FlateDecode >> stream x]n0 7d%=X|! YShm3p! V!ʘZǪ\2?"+\q|DV5k#3Ys"/-˂|q|_deW+tA&+L$g=]B#F)Ր+ endstream endobj 11 0 obj 360 endobj 12 0 obj << /Type /FontDescriptor /FontName /NimbusSansL /Flags 4 /FontBBox [ -173 -307 1097 979 ] /ItalicAngle 0 /Ascent 979 /Descent -307 /CapHeight 500 /StemV 80 /StemH 80 /FontFile 8 0 R >> endobj 5 0 obj << /Type /Font /Subtype /Type1 /BaseFont /NimbusSansL /FirstChar 0 /LastChar 31 /FontDescriptor 12 0 R /Widths [ 278 611 667 611 667 722 556 556 611 556 611 389 611 611 278 278 278 778 667 278 889 333 556 556 722 278 556 833 556 611 333 611 ] /ToUnicode 10 0 R >> endobj 13 0 obj << /Length 14 0 R /Filter /FlateDecode /Length1 16604 >> stream x{ |ExUs;Lf2dBDҁ$mHU*z7x,0 .YEWQVQW<@E#  }Ӽzuz;! /ڄoл~%^PVB|ެ g~b篜%Us0'k̩3_܂ṔS^9 %h?-Np,hvM>mӢM>?E BB'٦ZǞa,g0rT-rFGF4:6GFu3ݖMNMJ7/# &8Τx öFY}='XIwڅ'9>`=ΊQ>0߷~0 TޥL2¦IIgnxlˌArL$DDzN:](6JrQhwd2}dLku33dd+N5끜w|"kOհ=3jI+,f2SX]T7*uUvxZ:b}]"zLQc r٣iFs~uSI7E`t>7vgT3$7 @x6vYaqC~W>)o' 83L.Eՠ<XEd/DtKAh bv$7-rfŢXO7=H< E cЃ҃GLI#TFF-Y`z\#k׮ELzEF3ÙHatfv` 9pUpi[V( ڶ겁_dsLxF=s&}m5yf_t];z,_d-V9lU?ԵgQ`;5BK A;1= (ݰG*Jңٵy`l9`@Ѿc/=ڼ)<5x!xZͦv/(H46!+&q߼$ۓNwnXc HEc)0j[qj6mX]M{ ¸H/im;fvH1Gߏ'bBφV f6nYDNk/B잛T.O.-ԯVSwm׸~Q4=1wQ&lSl6aY:˱q8OUjj땉)Ɏ)I=ۈJcKNJ ,[Rq)쇝GeT7+֬[4bծVDk2:T`9*3]ϻI{;NY>$]=e_:Q+v] ]"ݚOҒ5Cfd "'2= =(3{-pBap`8S utջ7>^:tƎkp:F,.\L칳H!(#Om8e?9 G՗AQ c)by;0¤tl8!RE$[ ~a/ ȉJY3y@y#itBm;4v6il{"{dɴ9߾g^k$+ʐ雱0?~{G帩W\O6CLXC5B[z2AgMfp3oc/lߺH=K>_]b/qW|[|B?agD UPi{<0'|ƨSLg`DO+f`n1%rQHFɣDS bsyĢWQ 8g^5ܟeOeţ1:$鵓oCxonO_E,[QK&Ռ-:ۡgY勤,5rf|q !( l-_#Jٕ65m= be,yADhHx ˆ8q Y+f98#Ndڹtoa.H-1YƧdpL32'fG1u,DΈ*"%VʂVe)'XSSKxŀN5(ּw- ؏DW{3nvO"P.99RKO:}c6;hC|.~YP:>W*(U [GLOO9ys\o9<<\eccwΤ' Q") N|65FT+㸌Y`k)Sw>Y.՘."'N(0jZ"l:;We+Tkxq[&Բ>dq[|.Rر>yA=?3O=oy?_̗/;zKr o%;Ns+y梕g*R*ǝ 'mF 7fMnS{D7y'irpƜ]Nɐ{on\(%3WYEY!v ydKemD)*ҏF,~ ?iTdM ʶs'goP~d Ls9f8\Qh֛m Xaj\pvM4wc\bi4eҢV.{A4]:^oKȕ֮eX:o̝%܁nw=Sȣn\ zpzd]wvCvva@JgPF솼V>v2_;K#o~##bTo(71d@q;wϵrM<Ԥr#McYٟbdy1:Aэ:gqVtAעcuK0!B L~_CtIN#) g2]6ڦnV|<xϲ\9P﮾{_; gG{U iS g}dr]fL Doj2>WeDY^/Yyp,by3Y=TBB1FQ0Hl,g0J 3 7_g42O!ζo},9 e2YLKm *,׋2;NDh:Hgٳ,$8HjNeQˊ wYkY,~lD`q`h3dȢ #@\l1" +zA6,c1(`b2H]T @VЉVekd"wTm kL[: ڷ ,MQ {v@I{YQFE{Q"Vi 7!0*%hBU7ivO#cx3-`_mU,:a1qMZG`|U@6@o 7g{CZw]ȣwlGɁ.<6Ϝ8G~Dى}b@Skh_chSVǀ"+P vo/fxNjφ{>c>Bnyͣd'ɪ@|,w7ް& oqmįDLB A/Y%S4 0uY,{Z22:7e%̰|uVff坺ʋolzm o(^Y!lI*6NZ,zg.*^=%NRdU-LPuBXYg#!ɯSU>O_gz==:u+6ҏYG̬bń0뱦O+)au(s"]iW~vY3r L ؕQX(؎Ewwa/s*x]-r7v;;>?wϋ[j~0>U?!^_2%geRK3oQS2+R/9y'tGejԧi/Bxn.]3%H["-i{1PMQΪRz(P@뤺7_0,),By.O“HX#³\q-Jq\ހ7FU=zPG~=&^7ЫI\]sdNdPX.*KjG90YŐ$$ ,e2%QX%a.W颪RDN٫%l='*N}62wY{C+,7ri@?Los/@ԉO!/o vz us+xFR|#=]4ϳ*vrhp=~7nԻiٔ'2.n{ds _J3ԩx>u߈o9H-3-x17-Š,йsFQ5X:"|*AI^^>$KU 5ŕRVV2A,Qd(݂H:G|x\b#R>\I >=fZ1$D&"ClǓ\\<Հ L:8S ;Ucx Vw#\}!dRV.gQz_w"^Q#IIlEIIz#7zg`Ltw bI{yv[_RڂBRXPH"O,W33zpe#v+#[x0ȯ s^$D-NUAlQ^㻔NjhQbʿ2(zyS nq@۠0ۀBJ81g@MD*r:բ3n {=2[Xvb軄Szf  VL1Z"kzu?'[ uCSܸ~零X@ɿj@\9|x$WtqqkbD@H@ Rh3sJ HHD f3 WS9xxs(A = jAuWg)MwG.7^@h'zEϣCe|f/؁^'ߡUhk2k,GŮDEºEGzt+:ؙAw`:A:*CcމG&:t &Ԅ[5[O'~uRl:\Gm*E*<(z'f'~rXFD3W؉W1.'b@Ehzx8 puQѾhujGD/XϝO<B9ZO b=kڟD:QT # џq" 9=ϩ͉ h"i% 521dC^Eb7pfH?G3\pOp#zry}ONA"a0=6Nx1 ~N)a[v0v}#ZDϢc x^7{6|gI@sy xv1{ğ!XƂ>^S3a6<׭Nމwxq&' p"88t&2%L-V^S #|s;g`~#"_$OsR W#~и޹q6GgF܌W'o'. ī)$CI5\7l![Iy11)L63gf2KLyWYΆ;.eab7/x_;!aP/-N tf2^t)`]//S fM%;Fw n? ƣy6 ~l'`fQ#韼ocT¾كWz|+9Q;bxLaD'SX`E2vn43%vWf%?AGg.L o2݆摿n8x;݅ *z NE&>Ooֈw  p6t;gϑRt'sc(<7ρG͉h%Wþg#OB!4XUL>Jش}p(cFA4g$D 4h.uH'1X0oǡɉжltSb+ `Cbq'ݍvu[ J Uc\e/i% a'?J4{49.hwXmh]0BѤ-Q4~O>,9DO *DԲ2t5%,*7''+3Tr:)6Ŭ=s,C0ʩV6cїSc 1?tU^M7hd)U?($z+T7_ǎxYǺ(EsN?esZ+vm:yXpLojuPA-6aUbPXT,t1&T1uFlؚrO P7'MNИ)acb=?mtnTд~FpԺ3>7qڄ[lrôV8iu?cl͕Z=`. U6V£7id]mM GN讒= qиv[ݟ8 5@Zmq+Tꑾ9m967\YyyLiV52g1]QZPVR= ́u@ _-Y 1iXC21.#Ѐ`wWLCV\V5TE"l"0)q.웳MN 7uh4b-ckm?iGjn6FHץt A-LLZ1gP ?3ShmmՄZzk1CzkhuiFcCהzF Vj=_SF$Z9?NЯz=Uӷ2`pU&W%xm/Gja14NfAj;B'ˆQпdWo*BOo~T;Tkm +[Zv&ZJu?yTpIq:6ybkWs𠾚L_k{&eSG&G.&|U͇ρb1 ͟NDqeB yBug+P{ Br\5 ;,]:;hB(ҸE)d( D C/HY:`\j)wl5:ڳ` !ڈ8ڷ6ihO|95٬ך{MQc$٠$Yh$IbK(bِUfg8AMPbr0gb{{TƲ'# -C /v9L& rT;N=Fsgh7!|קSn,p9\Oc P 0`;!sJ|De^ @GP*CևPI$'ai*ފ/[qxz+{~'y>Nķ,@1;7?cxP 1sރ9GxcDrI2k9J^[5 I^!PQ+sa#ړa%e.@)@5xrY&/#`X|}c"R}jx蘟A@ aMZ 5Zo 5Zo^ 5Z/-3F)PEzԠ$+e&,…~dn=FdZeny -▵܈["ŋ[p[^-XY:q 7r;E9Ā5ށhkav߭j37.j O{p}R$U!ϗK$ٰ>^4:5G_!urR`-"E(ȋHD$lEs[A1bBo5MH Y*R5~(uMGUポX 1K0460R)$Ŋ"U1a 5mU 1Ct҉kuwz(Zwgm-rڗ:K-Cŕh-⼪j|MX>$Rkb\c?'>_QښϊqR^[[Չ'itȏt14t/%J҅`>ePtB]H4:SmÏk4+i&h :8P4Fȫx[#+In/IО_iIK4@fDh ۴l32o^ۛMCԙ`mpÃmbBM[:}:"8v1ѢugE7g //Etx8}V}V}pu,6 @{N}mjڕ!8od'A@-Cp萑&C[<!(dY1> stream x]j0F>EŠ; Bn\N\B!: ߾1_BM>f\Yfu юI`zTkTSg7_e5Ü5K?|qYOz!aoN͕ܬʲion"c}}\o[Yb"0G$5kZluJIa&!m;s<ˤl 2Pd WV {P@jz)@ AO'P 3P~ɣOW!5$#~8$RsU~9dw臯W"_~ F!~}( O9-y}FC?v /* endstream endobj 16 0 obj 373 endobj 17 0 obj << /Type /FontDescriptor /FontName /Arial /Flags 4 /FontBBox [ -664 -324 2028 1037 ] /ItalicAngle 0 /Ascent 905 /Descent -211 /CapHeight 1037 /StemV 80 /StemH 80 /FontFile2 13 0 R >> endobj 18 0 obj << /Type /Font /Subtype /CIDFontType2 /BaseFont /Arial /CIDSystemInfo << /Registry (Adobe) /Ordering (Identity) /Supplement 0 >> /FontDescriptor 17 0 R /W [0 [ 750 277 222 222 556 500 277 277 277 277 777 333 556 556 277 556 500 500 556 833 556 556 556 556 556 722 500 556 722 277 500 556 666 500 333 666 ]] >> endobj 6 0 obj << /Type /Font /Subtype /Type0 /BaseFont /Arial /Encoding /Identity-H /DescendantFonts [ 18 0 R] /ToUnicode 15 0 R >> endobj 1 0 obj << /Type /Pages /Kids [ 7 0 R ] /Count 1 >> endobj 19 0 obj << /Creator (cairo 1.8.0 (http://cairographics.org)) /Producer (cairo 1.8.0 (http://cairographics.org)) >> endobj 20 0 obj << /Type /Catalog /Pages 1 0 R >> endobj xref 0 21 0000000000 65535 f 0000105911 00000 n 0000073261 00000 n 0000000015 00000 n 0000073237 00000 n 0000091919 00000 n 0000105763 00000 n 0000073389 00000 n 0000073603 00000 n 0000091203 00000 n 0000091227 00000 n 0000091665 00000 n 0000091688 00000 n 0000092220 00000 n 0000104676 00000 n 0000104701 00000 n 0000105152 00000 n 0000105175 00000 n 0000105404 00000 n 0000105976 00000 n 0000106102 00000 n trailer << /Size 21 /Root 20 0 R /Info 19 0 R >> startxref 106155 %%EOF stxxl-1.3.1/doc/tutorial/vector.pdf0000644000175000017500000000622711437171771017137 0ustar andreasandreas%PDF-1.4 %쏢 5 0 obj <> stream xn0 z (Jan} zR'kZl{Qq$N>ؔ>_Zޫ|~y7#{a_Z,K$yT%ZL>|bxat|ZÓl(u`)yTa!La{q5UǶ'Ϙl:x\vӇ b Ĕ3yNlA5ܯ߈yIUL8VKGtOTDѬ^hDe U LviU] T GcGTSհokM-ΰ~_m̛jKL3"("Ɩr;WBݚjzi6}7paڨ[6 ,fh^td;/B :>˶(N9͋:#9u̟]}ڧ$:^V3!zc'ftPBG5?6N{FJF$Rxxݩ¼_(N~7+z'/Y4hƉ$X)roҜ8e]sjR~endstream endobj 6 0 obj 554 endobj 4 0 obj <> /Contents 5 0 R >> endobj 3 0 obj << /Type /Pages /Kids [ 4 0 R ] /Count 1 >> endobj 1 0 obj <> endobj 7 0 obj <>endobj 9 0 obj <> endobj 10 0 obj <> endobj 8 0 obj <> endobj 11 0 obj <>stream fig2dev Version 3.2 Patchlevel 5-alpha5 vector.figrdementi@mpino1302 \(Roman Dementiev,,,\) endstream endobj 2 0 obj <>endobj xref 0 12 0000000000 65535 f 0000000867 00000 n 0000002587 00000 n 0000000808 00000 n 0000000658 00000 n 0000000015 00000 n 0000000639 00000 n 0000000932 00000 n 0000001032 00000 n 0000000973 00000 n 0000001002 00000 n 0000001098 00000 n trailer << /Size 12 /Root 1 0 R /Info 2 0 R /ID [<18D6167055741AF70A4173806CA439BD><18D6167055741AF70A4173806CA439BD>] >> startxref 2830 %%EOF stxxl-1.3.1/doc/tutorial/Makefile0000644000175000017500000000076611460071375016577 0ustar andreasandreasall: tutorial tutorial: tutorial.pdf # try to use rules from LaTeX.mk (from latex-utils package) -include LaTeX.mk ifeq (,$(LU_UTILS)) # if LaTeX.mk is not available, fallback to our own rules tutorial.pdf: tutorial.tex tutorial.bib pdflatex tutorial bibtex tutorial pdflatex tutorial pdflatex tutorial clean: rm -rf *.bbl *.aux *~ *.dvi *.log *.toc *.blg *.idx distclean: clean $(RM) tutorial.pdf .PHONY: clean endif spell: ispell -d american tutorial.tex .PHONY: all tutorial spell stxxl-1.3.1/doc/tutorial/examples/0000755000175000017500000000000011536252420016740 5ustar andreasandreasstxxl-1.3.1/doc/tutorial/examples/phonebills.cpp0000644000175000017500000001063011352710176021606 0ustar andreasandreas/*************************************************************************** * phonebills.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2004 Roman Dementiev * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #include // Stxxl header #include // for STL sort #include // for STL vector #include #include #define CT_PER_MIN 2 struct LogEntry { long long int from; // callers number long long int to; // destination number time_t timestamp; // time of event int event; // event type 1 - call started // 2 - call ended }; std::istream & operator >> (std::istream & i, LogEntry & entry) { i >> entry.from; i >> entry.to; i >> entry.timestamp; i >> entry.event; return i; } std::ostream & operator << (std::ostream & i, const LogEntry & entry) { i << entry.from << " "; i << entry.to << " "; i << entry.timestamp << " "; i << entry.event; return i; } struct ProduceBill { std::ostream & out; unsigned sum; LogEntry last; ProduceBill(std::ostream & o_) : out(o_), sum(0) { last.from = -1; } void operator () (const LogEntry & e) { if (last.from == e.from) { // either the last event was 'call started' and current event // is 'call ended' or the last event was 'call ended' and // current event is 'call started' assert((last.event == 1 && e.event == 2) || (last.event == 2 && e.event == 1)); if (e.event == 2) // call ended sum += CT_PER_MIN * (e.timestamp - last.timestamp) / 60; } else if (last.from != -1) { assert(last.event == 2); // must be 'call ended' assert(e.event == 1); // must be 'call started' // output the total sum out << last.from << "; " << (sum / 100) << " EUR " << (sum % 100) << " ct" << std::endl; sum = 0; // reset the sum } last = e; } }; struct SortByCaller { // comparison function bool operator () (const LogEntry & a, const LogEntry & b) const { return a.from < b.from || (a.from == b.from && a.timestamp < b.timestamp) || (a.from == b.from && a.timestamp == b.timestamp && a.event < b.event); } // min sentinel = value which is strictly smaller that any input element static LogEntry min_value() { LogEntry e; e.from = (std::numeric_limits::min)(); return e; } // max sentinel = value which is strictly larger that any input element static LogEntry max_value() { LogEntry e; e.from = (std::numeric_limits::max)(); return e; } }; #ifdef USE_STXXL typedef stxxl::vector vector_type; #else typedef std::vector vector_type; #endif void print_usage(const char * program) { std::cout << "Usage: " << program << " logfile main billfile" << std::endl; std::cout << " logfile - file name of the input" << std::endl; std::cout << " main - memory to use (in MiB)" << std::endl; std::cout << " billfile - file name of the output" << std::endl; } int main(int argc, char * argv[]) { if (argc < 4) { print_usage(argv[0]); return 0; } // read from the file std::fstream in(argv[1], std::ios::in); vector_type v; std::copy(std::istream_iterator(in), std::istream_iterator(), std::back_inserter(v)); // sort by callers #ifndef USE_STXXL std::sort(v.begin(), v.end(), SortByCaller()); std::fstream out(argv[3], std::ios::out); // output bills std::for_each(v.begin(), v.end(), ProduceBill(out)); #else const unsigned M = atol(argv[2]) * 1024 * 1024; stxxl::sort(v.begin(), v.end(), SortByCaller(), M); std::fstream out(argv[3], std::ios::out); // output bills stxxl::for_each(v.begin(), v.end(), ProduceBill(out), M / vector_type::block_type::raw_size); #endif return 0; } stxxl-1.3.1/doc/tutorial/examples/genlog.cpp0000644000175000017500000000625211276774460020742 0ustar andreasandreas/*************************************************************************** * genlog.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2004 Roman Dementiev * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #include #include #include struct LogEntry { long long unsigned from; // callers number long long unsigned to; // destination number time_t timestamp; // time of event int event; // event type 1 - call started // 2 - call ended }; struct cmp { bool operator () (const LogEntry & a, const LogEntry & b) const { return a.timestamp < b.timestamp; } static LogEntry min_value() { LogEntry e; e.timestamp = (std::numeric_limits::min)(); return e; } static LogEntry max_value() { LogEntry e; e.timestamp = (std::numeric_limits::max)(); return e; } }; typedef stxxl::VECTOR_GENERATOR::result vector_type; std::ostream & operator << (std::ostream & i, const LogEntry & entry) { i << entry.from << " "; i << entry.to << " "; i << entry.timestamp << " "; i << entry.event << "\n"; return i; } int main(int argc, char * argv[]) { if (argc < 5) { STXXL_MSG("Usage: " << argv[0] << " ncalls avcalls main logfile"); STXXL_MSG(" ncalls - number of calls"); STXXL_MSG(" avcalls - average number of calls per client"); STXXL_MSG(" main - memory to use (in MiB)"); STXXL_MSG(" logfile - file name of the output"); return 0; } unsigned M = atol(argv[3]) * 1024 * 1024; const long long int ncalls = stxxl::atoint64(argv[1]); const int av_calls = atol(argv[2]); const long long int nclients = ncalls / av_calls; long long int calls_made = 0; time_t now = time(NULL); vector_type log; log.reserve(2 * ncalls); stxxl::random_number<> rnd; for (long long int number = 0; number < nclients && calls_made < ncalls; ++number) { unsigned serv = std::min(rnd(av_calls * 2), (ncalls - calls_made)); LogEntry e; e.from = number; time_t cur = now; while (serv-- > 0) { cur += 1 + rnd(3600 * 24); e.to = rnd(nclients); e.timestamp = cur; ++calls_made; e.event = 1; log.push_back(e); cur += 1 + rnd(1800); e.timestamp = cur; e.event = 2; log.push_back(e); } } // sort events in order of their appereance stxxl::sort(log.begin(), log.end(), cmp(), M); std::fstream out(argv[4], std::ios::out); std::copy(log.begin(), log.end(), std::ostream_iterator(out)); STXXL_MSG("\n" << calls_made << " calls made."); STXXL_MSG("The log is written to '" << argv[4] << "'."); return 0; } stxxl-1.3.1/doc/tutorial/examples/Makefile0000644000175000017500000000103011337600707020376 0ustar andreasandreasall: phonebills phonebills_stl genlog STXXL_MK ?= stxxl.mk -include ../../../$(STXXL_MK) CXX = $(STXXL_CXX) CPPFLAGS += -O3 CPPFLAGS += -W -Wall CPPFLAGS += $(STXXL_CPPFLAGS) phonebills: phonebills.cpp $(CXX) $(CPPFLAGS) phonebills.cpp -o phonebills $(STXXL_LDLIBS) -DUSE_STXXL phonebills_stl: phonebills.cpp $(CXX) $(CPPFLAGS) phonebills.cpp -o phonebills_stl $(STXXL_LDLIBS) -DNDEBUG genlog: genlog.cpp $(CXX) $(CPPFLAGS) genlog.cpp -o genlog $(STXXL_LDLIBS) -DNDEBUG clean: rm -f genlog phonebills_stl phonebills *~ stxxl-1.3.1/doc/tutorial/tutorial.bib0000644000175000017500000250600310647205664017463 0ustar andreasandreas @TechReport{SW05ext, author = {T. Schank and D. Wagner}, title = {Finding, counting and listing all triangles in large graphs, an experimental study}, institution = {Universit\"at Karlsruhe, Fakult\"at f\"ur Informatik}, year = {2005}, OPTkey = {}, OPTtype = {}, OPTnumber = {}, OPTaddress = {}, OPTmonth = {}, OPTnote = {}, OPTannote = {} } @InProceedings{SW05, author = {T. Schank and D. Wagner}, title = {Finding, counting and listing all triangles in large graphs, an experimental study.}, booktitle = {4th International Workshop on Experimental and Efficient Algorithms (WEA'05)}, OPTcrossref = {}, OPTkey = {}, OPTpages = {}, year = {2005}, OPTeditor = {}, volume = {3503}, OPTnumber = {}, series = {lncs}, OPTaddress = {}, OPTmonth = {}, OPTorganization = {}, publisher = {Springer}, OPTnote = {}, OPTannote = {} } @Article{WS98, author = {D.J. Watts and S. H. Strogatz}, title = {Collective dynamics of ``small-world'' networks}, journal = {Nature}, year = {1998}, OPTkey = {}, volume = {393}, OPTnumber = {}, pages = {440-442}, OPTmonth = {}, OPTnote = {}, OPTannote = {} } @InProceedings{LLMMS03, author = {L. Laura and S. Leonardi and S. Millozzi and U. Meyer and J. F. Sibeyn}, title = {Algorithms and Experiments for the Webgraph}, booktitle = proc # "11th " # esa, publisher = springer, series = lncs, OPTvolume = 2461, pages = "703--714", year = 2003, } @MastersThesis{AjwaniThesis, author = {D. Ajwani}, title = {Design, implementation and experimental study of external memory BFS algorithms}, school = {Universit\"at des Saarlandes}, year = {2005}, OPTkey = {}, OPTtype = {}, OPTaddress = {}, OPTmonth = {}, OPTnote = {}, OPTannote = {} } @article{MM93, author = "U. Manber and G. Myers", title = "Suffix Arrays: A New Method For On-Line String Searches", journal = sicomp, volume = 22, number = 5, year = 1993, month = oct, pages = "935--948" } @article{Haanpaa2004, author = {Harri Haanp\"a\"a}, journal = {Journal of Integer Sequences}, number = {2}, pages = {article 04.1.8}, title = {Minimum Sum and Difference Covers of {A}belian Groups}, volume = {7}, year = {2004}, } @Article{SS01, author = {K. Sadakane and T.Shibuya}, title = {Indexing Huge Genome Sequences for Solving Various Problems}, journal = {Genome Informatics}, year = {2001}, volume = {12}, pages = {175--183}, } @inproceedings{LSSY02, author = "T.-W. Lam and K. Sadakane and W.-K. Sung and Siu-Ming Yiu", title = "A Space and Time Efficient Algorithm for Constructing Compressed Suffix Arrays", booktitle = proc # "8th " # cocoon, publisher = springer, series = lncs, volume = 2387, year = 2002, pages = "401--410", } @InProceedings{MF02, author = "G. Manzini and P. Ferragina", title = "Engineering a lightweight suffix array construction algorithm", booktitle = proc # "10th " # esa, publisher = springer, series = lncs, volume = 2461, pages = "698--710", year = 2002, } @InCollection{GBYS92, author = "G. Gonnet and R. Baeza-Yates and T. Snider", title = "New Indices for Text: {PAT} trees and {PAT} arrays", booktitle = "Information Retrieval: Data Structures \& Algorithms", editor = "W. B. Frakes and R. Baeza-Yates", publisher = "Prentice-Hall", year = "1992", } @TechReport{BW94, author = "M. Burrows and D. J. Wheeler", title = "A block-sorting lossless data compression algorithm.", institution = "SRC (digital, Palo Alto)", type = "Technical Report", number = "124", month = may, year = "1994", } @Article{KarSan05, author = "J. K{\"a}rkk{\"a}inen and P. Sanders and S. Burkhardt", title = "Linear Work Suffix Array Construction", journal = "Journal of the ACM", year = 2005, note = "accepted for publication" } @InProceedings{KSPP03, title = "Linear-Time Construction of Suffix Arrays", author = "D. K. Kim and J. S. Sim and H. Park and K. Park", booktitle = proc # "14th " # cpm, publisher = "Springer", month = jun, series = lncs, volume = "2676", pages = "186-199", year = 2003, } @InProceedings{KA03, title = "Space Efficient Linear Time Construction of Suffix Arrays", author = "P. Ko and S. Aluru", booktitle = proc # "14th " # cpm, publisher = "Springer", series = lncs, volume = "2089", pages = "200--210", year = 2003, } @Article{CF02, author = "A. Crauser and P. Ferragina", title = "Theoretical and Experimental Study on the Construction of Suffix Arrays in External Memory", journal = "Algorithmica", volume = "32", number = "1", pages = "1--35", year = "2002", } @InProceedings{AKO02b, author = "M. I. Abouelhoda and S. Kurtz and E. Ohlebusch", title = "The Enhanced Suffix Array and Its Applications to Genome Analysis", booktitle = proc # "2nd " # "Workshop on Algorithms in Bioinformatics", series = lncs, volume = "2452", publisher = springer, pages = "449--463", year = "2002", } @Article{DKMS06, author = {R. Dementiev and J. K\"arkk\"ainen and J. Mehnert and P. Sanders}, title = {Better External Memory Suffix Array Construction}, journal = {ACM Journal of Experimental Algorithmics}, volume = X, year = 2006, note = "to appear" } @Article{Chazelle00, author = {B. Chazelle}, title = {A Minimum Spanning Tree Algorithm with Inverse-Ackermann Type Complexity}, journal = {Journal of the ACM}, year = {2000}, key = {47}, OPTvolume = {}, OPTnumber = {}, pages = {1028-1047}, OPTmonth = {}, OPTnote = {}, OPTannote = {} } @Misc{DominikBachelor, OPTkey = {}, author = {D. Schultes}, title = {External memory minimum spanning trees}, howpublished = {Bachelor thesis, Max-Planck-Institut f. Informatik and Saarland University, {\url{http://www.dominik-schultes.de/emmst/}}}, month = {August}, year = {2003}, OPTnote = {}, OPTannote = {} } @InProceedings{BDIW02, author = {M. Bander and Z. Duan and J. Iacono and J. Wu}, title = {A locality-preserving cache-oblivious dynamic dictionary}, booktitle = {13th Annual ACM-SIAM Symposium On Descrete Algorithms (SODA-02)}, OPTcrossref = {}, OPTkey = {}, OPTpages = {}, year = {2002}, OPTeditor = {}, OPTvolume = {}, OPTnumber = {}, OPTseries = {}, OPTaddress = {}, OPTmonth = {}, OPTorganization = {}, OPTpublisher = {}, OPTnote = {}, OPTannote = {} } @InProceedings{BDB99, author = {Michael A. Olson and Keith Bostic and Margo Seltzer }, title = "{Berkeley DB}", booktitle = "{USENIX Annual Technical Conference}", OPTcrossref = {}, OPTkey = {}, pages = {183–192}, year = {1999}, OPTeditor = {}, OPTvolume = {}, OPTnumber = {}, OPTseries = {}, OPTaddress = {}, month = {June}, OPTorganization = {}, OPTpublisher = {}, OPTnote = {}, OPTannote = {} } @Article{BM72, author = {R. Bayer and E. McCreight}, title = {Organization and maintenance of large ordered indices}, journal = {Acta Informatica}, year = {1972}, OPTkey = {}, OPTvolume = {1}, OPTnumber = {1}, pages = {173–189}, OPTmonth = {}, OPTnote = {}, OPTannote = {} } @INPROCEEDINGS{Ajwani06, AUTHOR = {Ajwani, Deepak and Dementiev, Roman and Meyer, Ulrich}, TITLE = "{A computational study of external memory BFS algorithms}", BOOKTITLE = {ACM-SIAM Symposium on Discrete Algorithms (SODA-06)}, PUBLISHER = {ACM}, YEAR = {2006}, PAGES = {601-610}, ADDRESS = {Miami, USA}, } @TechReport{DKS05ext, author = {R. Dementiev and L. Kettner and P. Sanders}, title = "{Stxxl: Standard Template Library for XXL Data Sets}", institution = {Fakult\"at f\"ur Informatik, University of Karlsruhe}, year = {2005}, OPTkey = {}, OPTtype = {}, number = {18}, OPTaddress = {}, OPTmonth = {}, OPTnote = {}, OPTannote = {} } @Article{Finocchi05, author = {I. Finocchi and A. Panconesi and R. Silvestri}, title = {An Experimental Analysis of Simple, Distributed Vertex Coloring Algorithms}, journal = {Algorithmica}, year = {2005}, OPTkey = {}, volume = {41}, OPTnumber = {}, pages = {1-23}, OPTmonth = {}, OPTnote = {}, OPTannote = {} } @Misc{Culberson, OPTkey = {}, author = {J.C. Culberson}, OPTtitle = "{}", note = {\url{http://web.cs.ualberta.ca/~joe/Coloring/}}, OPTmonth = {}, OPTyear = {}, OPTnote = {}, OPTannote = {} } @TechReport{Allwright95, author = {J.R. Allwright and R. Bordawekar and P.D. Coddington and K. Dincer and C.L. Martin}, title = {A comparison of parallel graph coloring algorithms}, institution = {Northeast Parallel Architecture Center, Syracuse University}, year = {1995}, OPTkey = {}, OPTtype = {}, OPTnumber = {}, OPTaddress = {}, OPTmonth = {}, OPTnote = {}, OPTannote = {} } @Article{JonesPlassmann93, author = {M.T. Jones and P.E. Plassmann}, title = {A parallel graph coloring heuristics}, journal = {SIAM Joirnal on Scientific Computing}, year = {1993}, OPTkey = {}, volume = {14}, number = {3}, pages = {654-669}, OPTmonth = {}, OPTnote = {}, OPTannote = {} } @InProceedings{DKS05, author = {R. Dementiev and L. Kettner and P. Sanders}, title = "{Stxxl: Standard Template Library for XXL Data Sets}", booktitle = "{13th Ann. European Symposium on Algorithms (ESA)}", OPTcrossref = {}, OPTkey = {}, OPTeditor = {}, OPTaddress = {}, volume = 3669, year = 2005, series = "{LNCS}", OPTmonth = {}, OPTorganization = {}, publisher = {Springer}, OPTnote = {}, OPTannote = {}, pages = {640-651}, } @Article{Welsh67, author = {D. J. A. Welsh and M. B. Powel}, title = {An Upper Bound for the Chromatic Number of a Graph and its Application to Timetabling Problems}, journal = {Computing Journal}, year = {1967}, OPTkey = {}, volume = {10}, number = {85}, OPTpages = {}, OPTmonth = {}, OPTnote = {}, OPTannote = {} } @Book{Matula72, author = {D. W. Matula and G. Marble and J.D. Isaacson}, ALTeditor = {}, title = {Graph Coloring Algorithms}, publisher = {Academic Press}, year = {1972}, OPTkey = {}, OPTvolume = {}, OPTnumber = {}, OPTseries = {}, address = {New York}, OPTedition = {}, OPTmonth = {}, OPTnote = {}, OPTannote = {} } @InProceedings{AgarwalArgeYi2005, author = {Pankaj K. Agarwal and Lars Arge and Ke Yi}, title = "{I/O-Efficient Construction of Constrained Delaunay Triangulations}", booktitle = {13th European Symposium on Algorithms (ESA '05)}, OPTcrossref = {}, OPTkey = {}, pages = {355-366}, year = {2005}, OPTeditor = {}, OPTvolume = {}, number = {3669}, series = {LNCS}, OPTaddress = {}, OPTmonth = {}, OPTorganization = {}, OPTpublisher = {}, OPTnote = {}, OPTannote = {} } @Misc{StreamBench, OPTkey = {}, OPTauthor = {}, title = "{The STREAM Benchmark: Computer Memory Bandwidth.}", note = {\url{http://www.streambench.org/}}, OPTmonth = {}, OPTyear = {}, OPTnote = {}, OPTannote = {} } @Article{Garey76, author = {M. R. Garey and D. S. Johnson and L. Stockmeyer}, title = "{Some simplified NP-complete graph problems}", journal = {Theoret. Comput. Sci.}, year = {1976}, OPTkey = {}, volume = {1}, OPTnumber = {}, pages = {237-267}, OPTmonth = {}, OPTnote = {}, OPTannote = {} } @InProceedings{Robertson96, author = {Neil Robertson and Daniel P. Sanders and Paul Seymour and Robin Thomas}, title = {Efficiently four-coloring planar graphs}, booktitle = "{Twenty-eighth annual ACM symposium on Theory of computing}", OPTcrossref = {}, OPTkey = {}, pages = { 571 - 575}, year = {1996}, OPTeditor = {}, OPTvolume = {}, OPTnumber = {}, OPTseries = {}, OPTaddress = {}, OPTmonth = {}, OPTorganization = {}, OPTpublisher = {}, OPTnote = {}, OPTannote = {} } @Article{Frederickson84, author = {Greg N. Frederickson}, title = {On linear-time algorithms for five-coloring planar graphs}, journal = {Information Processing Letters}, year = {1984}, OPTkey = {}, volume = {19}, number = {5}, pages = {219 - 224}, month = {November}, OPTnote = {}, OPTannote = {} } @InProceedings{AlonColoring, author = "Noga Alon", title = "A simple algorithm for edge-coloring bipartite multigraphs", booktitle = "Information Processing Letters, Vol. 85, issue 6", pages = "301--302", year = 2003 } @article{Hagerup, author = {Torben Hagerup and Marek Chrobak and Krzysztof Diks}, title = {Optimal parallel 5-colouring of planar graphs}, journal = {SIAM J. Comput.}, volume = {18}, number = {2}, year = {1989}, issn = {0097-5397}, pages = {288--300}, publisher = {Society for Industrial and Applied Mathematics}, } @article{Boyar, author = {Joan F. Boyar and Howard J. Karloff}, title = {Coloring Planar Graphs in Parallel}, journal = {J. Algorithms}, volume = {8}, number = {4}, year = {1987}, pages = {470--479} } @InProceedings{Naor, author = "Joseph Naor", title = "A Fast Parallel COloring of Planar Graphs with five colors", booktitle = "Information Processing Letters, Vol. 25, issue ?", pages = "51--53", year = 1987 } @inproceedings{ Goldberg, author = "A. Goldberg and S. Plotkin and G. Shannon", title = "Parallel symmetry-breaking in sparse graphs", pages = "315--324", year = "1987" } @InProceedings{Bauernoeppel85, author = {F. Bauern\"oppel and H. Jung}, title = {Fast parallel vertex colouring}, booktitle = {5th International Conference on Fundamentals of Computational Theory}, OPTcrossref = {}, OPTkey = {}, pages = {28-35}, year = {1985}, OPTeditor = {}, OPTvolume = {}, OPTnumber = {}, series = {LNCS 199}, OPTaddress = {}, OPTmonth = {}, OPTorganization = {}, OPTpublisher = {}, OPTnote = {}, OPTannote = {} } @inproceedings( Diks, author= {Krzysztof Diks}, title= { A Fast Parallel Algorithm for Six-Colouring of Planar Graphs (Extended Abstract)}, booktitle= { Mathematical Foundations of Computer Science 1986 (Proceedings of the Twelfth Symposium Held in Bratislava, Czechoslovakia)}, year= 1986, editor= {J. Gruska and B. Rovan and J. Wiedermann}, pages= {273--282}, publisher= {Springer-Verlag}, address= {Berlin}, series= {LNCS}, volume= 233, keywords= {graph color}, mrnumbers= { 87m#68008}, classif= {Planar/Parallel Coloring} ) @MastersThesis{JensThesis, author = {Jens Mehnert}, title = "{External Memory Suffix Array Construction}", school = {University of Saarland, Germany}, year = {2004}, OPTkey = {}, OPTtype = {}, OPTaddress = {}, month = {November}, note = "{\url{http://algo2.iti.uka.de/dementiev/esuffix/docu/data/diplom.pdf}}", OPTannote = {} } @Article{HK79, author = {Frank Harary and Helene J. Kommel}, title = {Matrix measures for transitivity and balance}, journal = {Journal of Mathematical Sociology}, year = {1979}, OPTkey = {}, volume = {6}, OPTnumber = {}, pages = {199-210}, OPTmonth = {}, OPTnote = {}, OPTannote = {} } @Book{SzarneckiGenerProgr, author = {Krzysztof Czarnecki and Ulrich Eisenecker}, ALTeditor = {}, title = "{Generative Programming: Methods, Tools, and Applications}", publisher = "{Addison Wesley Professional}", year = {2000}, OPTkey = {}, OPTvolume = {}, OPTnumber = {}, OPTseries = {}, OPTaddress = {}, OPTedition = {}, OPTmonth = {}, note = "{\url{http://www.generative-programming.org/}}", OPTannote = {} } @InProceedings{FG05, author = {E. R. Davidson and T. H. Cormen}, title = "{Building on a Framework: Using FG for More Flexibility and Improved Performance in Parallel Programs}", booktitle = "{19th International Parallel and Distributed Processing Symposium (IPDPS 2005)}", OPTcrossref = {}, OPTkey = {}, OPTpages = {}, OPTyear = {}, OPTeditor = {}, OPTvolume = {}, OPTnumber = {}, OPTseries = {}, OPTaddress = {}, OPTmonth = {}, OPTorganization = {}, OPTpublisher = {}, note = {to appear}, OPTannote = {} } @Misc{SchultesCC03, author = {Dominik Schultes}, title = "{External Memory Spanning Forests and Connected Components}", howpublished = "{\url{http://i10www.ira.uka.de/dementiev/files/cc.pdf}}", month = {September}, year = {2003}, OPTnote = {}, OPTannote = {} } @InProceedings{Vengroff94, author = {D. E. Vengroff}, title = "{A Transparent Parallel I/O Environment}", booktitle = {Third DAGS Symposium on Parallel Computation}, OPTcrossref = {}, OPTkey = {}, pages = {117-134}, year = {1994}, OPTeditor = {}, OPTvolume = {}, OPTnumber = {}, OPTseries = {}, address = {Hanover, NH}, month = {July}, OPTorganization = {}, OPTpublisher = {}, OPTnote = {}, OPTannote = {} } @MastersThesis{Ajwani05, author = {Deepak Ajwani}, title = "{Design, Implementation and Experimental Study of External Memory BFS Algorithms}", school = "{Max-Planck-Institut f\"ur Informatik}", year = {2005}, OPTkey = {}, OPTtype = {}, address = "{Saarbr\"ucken, Germany}", month = {January}, OPTnote = {}, OPTannote = {} } @InProceedings{MM02, author = {K. Mehlhorn and U. Meyer}, title = "{External-Memory Breadth-First Search with Sublinear I/O}", booktitle = "{10th Ann. European Symposium on Algorithms (ESA)}", OPTcrossref = {}, OPTkey = {}, pages = {723-735}, year = {2002}, OPTeditor = {}, volume = {2461}, number = {723}, series = "{LNCS}", OPTaddress = {}, OPTmonth = {}, OPTorganization = {}, OPTpublisher = {}, OPTnote = {}, OPTannote = {} } @Article{Brengel00, author = {Klaus Brengel and Andreas Crauser and Paolo Ferragina and Ulrich Meyer}, title = {An Experimental Study of Priority Queues in External Memory}, journal = {ACM Journal of Experimental Algorithms}, year = {2000}, volume = {5}, number = {17}, OPTpages = {}, OPTmonth = {}, OPTnote = {}, OPTannote = {} } @PhdThesis{ZehPhd, author = {Norbert Ralf Zeh}, title = "{I/O Efficient Algorithms for Shortest Path Related Problems}", school = {Carleton University, Ottawa}, year = {2002}, OPTkey = {}, OPTtype = {}, OPTaddress = {}, month = {April}, OPTnote = {}, OPTannote = {} } @InProceedings{TPIEscientific96, author = {D. E. Vengroff and J. S. Vitter}, title = "{I/O-Efficient Scientific Computation using TPIE}", booktitle = {Goddard Conference on Mass Storage Systems and Technologies}, OPTcrossref = {}, OPTkey = {}, pages = {553--570}, year = {1996}, OPTeditor = {}, volume = {2}, OPTnumber = {}, OPTseries = {}, OPTaddress = {}, OPTmonth = {}, OPTorganization = {}, OPTpublisher = {}, note = {published in NASA Conference Publication 3340}, OPTannote = {} } @PhdThesis{ChiangPHD, author = {Y.-J. Chiang}, title = {Dynamic and I/O-Efficient Algorithms for Computational Geometry and Graph Algorithms}, school = {Brown University}, year = {1995} } @InProceedings{APV02, author = "L. Arge and O. Procopiuc and J. S. Vitter", title = "{Implementing I/O-efficient Data Structures Using TPIE}", booktitle = "10th European Symposium on Algorithms (ESA)", pages = "88--100", year = 2002, volume = 2461, series = "LNCS", publisher = "Springer" } @InProceedings{CraMeh99, author = "A. Crauser and K. Mehlhorn", title = "{LEDA-SM}, extending {LEDA} to Secondary Memory", booktitle = "3rd International Workshop on Algorithmic Engineering (WAE)", pages = "228--242", year = 1999, volume = 1668, series = "LNCS" } @Article{VitShr94both, author = "J. S. Vitter and E. A. M. Shriver", title = "Algorithms for parallel memory, {I/II}", journal = "Algorithmica", year = 1994, volume = 12, number = "2/3", pages = "110--169" } @InProceedings{Bkdtree03, author = {O. Procopiuc and P. K. Agarwal and L. Arge and J. S. Vitter}, title = "{Bkd-tree: A Dynamic Scalable KD-Tree}", booktitle = {Proc. 8th Int'l Symposium on Spatial and Temporal Databases (SSTD '03)}, pages = {46-65} } @InProceedings{DynRTrees99, author = {L. Arge and K. H. Hinrichs and J. Vahrenhold and J. S. Vitter}, title = "{Efficient Bulk Operations on Dynamic R-trees}", booktitle = {1st Workshop on Algorithm Engineering and Experimentation (ALENEX '99)}, OPTcrossref = {}, OPTkey = {}, pages = {328-348}, year = {1999}, OPTeditor = {}, OPTvolume = {}, OPTnumber = {}, series = {Lecture Notes in Computer Science}, OPTaddress = {}, OPTmonth = {}, OPTorganization = {}, publisher = {Springer-Verlag}, OPTnote = {}, OPTannote = {} } @InProceedings{CRBtree03, author = {P. K. Agarwal and L. Arge and S. Govindarajan}, title = "{CRB-Tree: An Efficient Indexing Scheme for Range Aggregate Queries}", booktitle = {Proc. 9th Int'l Conference on Database Theory (ICDT '03)}, OPTcrossref = {}, OPTkey = {}, pages = {143-157}, year = {2003}, OPTeditor = {}, OPTvolume = {}, OPTnumber = {}, OPTseries = {}, OPTaddress = {}, OPTmonth = {}, OPTorganization = {}, OPTpublisher = {}, OPTnote = {}, OPTannote = {} } @PHDTHESIS{andreas_diss, AUTHOR = {A. Crauser}, TITLE = "{LEDA-SM: External Memory Algorithms and Data Structures in Theory and Practice}", ADDRESS = {Saarbr{\"u}cken}, YEAR = {2001}, SCHOOL = {Universit{\"a}t des Saarlandes}, LOCATION = {Fachbereichsbibliothek Informatik}, BIBTYPE = {PHDTHESIS} } @manual{ ledasm_manual, author = "{Andreas Crauser, Kurt Mehlhorn}", title = "{LEDA-SM: A Platform for Secondary Memory Computation}", year = 1999 } @manual{ tpie_manual, author ="{Lars Arge, Rakesh Barve, David Hutchinson, Octavian Procopiuc, Laura Toma, Darren Erik Vengroff, Rajiv Wickeremesinghe}", title ="{TPIE: User manual and reference}", year = 2003, month = {November} } @techreport{ stepanov94standard, author = "A. A. Stepanov and M. Lee", title = "{The Standard Template Library}", number = "X3J16/94-0095, WG21/N0482", year = "1994", institution = "Silicon Graphics Inc., Hewlett Packard Laboratories" } @Misc{ Moore2000, author = {R. W. Moore}, title = {Enabling Petabyte Computing}, howpublished = {\url{http://www.nap.edu/html/whitepapers/ch-48.html}}, year = {2000} } @InBook{BillingLarge, author = {Andrew Hume}, title = {Handbook of massive data sets}, chapter = {Billing in the large}, publisher = {Kluwer Academic Publishers}, year = {2002}, pages = {895 -- 909} } Article{VitShr94both, author = "J. S. Vitter and E. A. M. Shriver", title = "Algorithms for parallel memory, {I/II}", journal = "Algorithmica", year = 1994, volume = 12, number = "2/3", pages = "110--169" } % Abkuerzungen @string{sicomp = "SIAM Journal on Computing"} @String{acmcs = "{ACM} Computing Surveys"} @String{uka = "Universit{\"a}t Karlsruhe"} @String{aint = "Artificial Intelligence"} @String{cacm = "Communications of the ACM"} @String{fgcs = "Future Generation Computing Systems"} @String{focs = "Foundations of Computer Science"} @String{icpp = "International Conference on Parallel Processing"} @String{ipps = "International Parallel Processing Symposium"} @String{ijpp = "International Journal of Parallel Programming"} @String{jacm = "Journal of the ACM"} @String{jpdc = "Journal of Parallel and Distributed Computing"} @String{paco = "Parallel Computing"} @String{pdpta = "International Conference on Parallel and Distributed Processing Techniques and Applications"} @String{tpds = "IEEE Transactions on Parallel and Distributed Systems"} @String{pami = "IEEE Transactions on Pattern Analysis and Machine Intelligence"} @String{ietc = "IEEE Transactions on Computers"} @String{ipl = "Information Processing Letters"} @String{spaa = "ACM Symposium on Parallel Architectures and Algorithms"} @String{stoc = "ACM Symposium on the Theory of Computing"} @BOOK{compiler, author = "Steven S. Muchnick", title = "Advanced {C}ompiler {D}esign and {I}mplementation", publisher = "Morgan Kaufmann Publishers", address = "San Francisco, Kalifornien", year = "1997" } @InProceedings{Itanium2-L2, author = {Reid Riedlinger and Tom Grutkowski}, title = {The {H}igh {B}andwidth, 256{KB} 2nd {L}evel {C}ache on an {I}tanium{\texttrademark} {M}icroprocessor}, booktitle = {Proceedings of the IEEE International Solid-State Circuits Conference}, month = feb, year = {2002}, address = {San Francisco} } @article{introsort, author = {David R. Musser}, title = {Introspective sorting and selection algorithms}, journal = {Softw. Pract. Exper.}, volume = {27}, number = {8}, year = {1997}, issn = {0038-0644}, pages = {983--993}, publisher = {John Wiley \& Sons, Inc.}, } @ARTICLE{intel-compiler, author = "Carole Dulong and Rakesh Krishnaiyer and Dattatraya Kulkarni and Daniel Lavery and Wei Li and John Ng and David Sehr", title = "An {O}verview of the {I}ntel {IA}-64 {C}ompiler", journal = "Intel Technology Journal", number = "Q4", year = 1999, } @article{SWP-survey, author = {Allan, V.H. and Jones, R.B. and Lee, R.M. and Allan, S.J.}, title = {{S}oftware {P}ipelining}, journal = {{C}omputing {S}urveys}, year = {1995}, month = sep, volume = {27}, number = {3}, pages = {367--432} } @manual{ita2opt, title = {Intel {I}tanium 2 {P}rocessor {R}eference Manual for {S}oftware Development and {O}ptimization}, organization = {Intel}, year = {2003}, month = apr } @InProceedings{SW04, author = "P. Sanders and S. Winkel", title = "Super Scalar Sample Sort", booktitle = "12th European Symposium on Algorithms (ESA)", year = 2004, publisher = "Springer", series = "LNCS", volume = "3221", pages = "784--796" } @InProceedings{SW04www, author = "P. Sanders and S. Winkel", title = "\htmladdnormallink{Super Scalar Sample Sort}{ssss.ps.gz}", booktitle = "12th European Symposium on Algorithms (ESA)", year = 2004, publisher = "Springer {\copyright}", series = "{\htmladdnormallink{LNCS}{http://www.springer.de/comp/lncs/index}}", volume = "3221", pages = "784--796" } @TechReport{PS04b, author = "S. Pettie and P. Sanders", title = "A Simpler Linear Time $2/3-\epsilon$ Approximation\\ for Maximum Weight Matching", institution = "MPII", year = 2004, number = "MPI-I-2004-1-002" } @Article{PS04, author = "S. Pettie and P. Sanders", title = "A Simpler Linear Time $2/3-\epsilon$ Approximation\\ for Maximum Weight Matching", note = "in press", journal = "Information Processing Letters", year = 2004 } @InProceedings{San04awww, author = "P. Sanders", title = "\htmladdnormallink{Algorithms for Scalable Storage Servers}{storage.ps.gz}", booktitle = "SOFSEM 2004: Theory and Practice of Computer Science", pages = "82--101", publisher = "Springer {\copyright}", series = "{\htmladdnormallink{LNCS}{http://www.springer.de/comp/lncs/index.html}}", year = 2004, volume = 2932 } @InProceedings{San04a, author = "P. Sanders", title = "Algorithms for Scalable Storage Servers", booktitle = "SOFSEM 2004: Theory and Practice of Computer Science", pages = "82--101", publisher = "Springer", series = "LNCS", year = 2004, volume = 2932 } @Unpublished{Dem03, author = "R. Dementiev", title = "The \stxxl library", note = "Documentation and download at {\url{http://stxxl.sourceforge.net/}}", OPTkey = "", OPTmonth = "", OPTyear = "2003", OPTannote = "" } @InProceedings{DKMS05www, author = "R. Dementiev and J. Mehnert and J. K{\"a}rkk{\"a}inen and P. Sanders", title = "\htmladdnormallink{Better External Memory Suffix Array Construction}{DKMS05.pdf}", booktitle = "Workshop on Algorithm Engineering {\&} Experiments", year = 2005, address = "Vancouver" } @InProceedings{DKMS05, author = "R. Dementiev and J. Mehnert and J. K{\"a}rkk{\"a}inen and P. Sanders", title = "{Better External Memory Suffix Array Construction}", booktitle = "Workshop on Algorithm Engineering {\&} Experiments", year = 2005, address = "Vancouver", note = "\url{http://i10www.ira.uka.de/dementiev/files/DKMS05.pdf}" } @InProceedings{DKMS04, author = "R. Dementiev and L. Kettner and J. Mehnert and P. Sanders", title = "Engineering a Sorted List Data Structure for 32 Bit Keys", booktitle = "Workshop on Algorithm Engineering {\&} Experiments", year = 2004, address = "New Orleans", } @InProceedings{DKMS04www, author = "R. Dementiev and L. Kettner and J. Mehnert and P. Sanders", title = "\htmladdnormallink{Engineering a Sorted List Data Structure for 32 Bit Keys}{veb.ps.gz}", booktitle = "Workshop on Algorithm Engineering {\&} Experiments", year = 2004, address = "New Orleans", pages = "142--151" } @InProceedings{KarSan03, author = "J. K{\"a}rkk{\"a}inen and P. Sanders", title = "Simple Linear Work Suffix Array Construction", booktitle = "30th International Colloquium on Automata, Languages and Programming", series = "LNCS", year = 2003, pages = "943--955", number = 2719, } @InProceedings{KarSan03www, author = "J. K{\"a}rkk{\"a}inen and P. Sanders", title = "\htmladdnormallink{Simple Linear Work Suffix Array Construction}{suffix.ps.gz}", booktitle = "30th International Colloquium on Automata, Languages and Programming", year = 2003, pages = "943--955", publisher = "Springer {\copyright}", series = "{\htmladdnormallink{LNCS}{http://www.springer.de/comp/lncs/index.html}}", number = 2719, } @Book{MSS03www, editor = "U. Meyer and P. Sanders and J. Sibeyn", title = "\htmladdnormallink{Algorithms for Memory Hierarchies}{http://link.springer-ny.com/link/service/series/0558/tocs/t2625.htm}", publisher = "Springer", year = 2003, volume = 2625, series = "LNCS Tutorial" } @Book{MSS03, editor = "U. Meyer and P. Sanders and J. Sibeyn", title = "Algorithms for Memory Hierarchies", publisher = "Springer", year = 2003, volume = 2625, series = "LNCS Tutorial" } @TECHREPORT{KSV03, AUTHOR = {Krysta, P. and Sanders, P. and V{\"o}cking, B.}, TITLE = {Scheduling and Traffic Allocation for Tasks with Bounded Splittability }, TYPE = {Research Report}, INSTITUTION = {Max-Planck-Institut f{\"u}r Informatik}, NUMBER = {MPI-I-2003-1-002}, MONTH = {February}, YEAR = {2003}, ISSN = {0946-011X}, } @InProceedings{KSV03a, author = "Krysta, P. and Sanders, P. and V{\"o}cking, B.", title = "Scheduling and Traffic Allocation for Tasks with Bounded Splittability", booktitle = "28th International Symposium on Mathematical Foundations of Computer Science", pages = "500--510", year = 2003, series = "LNCS", number = 2747, publisher = "Springer" } @InBook{San03a, author = "P. Sanders", title = "Algorithms for Memory Hierarchies", chapter = "1: Memory Hierarchies --- Models and Lower Bounds", publisher = "Springer", year = 2003, volume = 2625, series = "LNCS Tutorial", pages = "1--13" } @InProceedings{SanFle00, author = "P. Sanders and R. Fleischer", title = "Asymptotic Complexity from Experiments? A Case Study for Randomized Algorithms", booktitle = "Workshop on Algorithm Engineering", year = 2000, series = "LNCS", number = 1982, pages = "135--146", } @InProceedings{SanFle00www, author = "P. Sanders and R. Fleischer", pages = "135--146", title = "\htmladdnormallink{Asymptotic Complexity from Experiments? {A} Case Study for Randomized Algorithms}{wae00.ps.gz}", booktitle = "Workshop on Algorithm Engineering", year = 2000, number = 1982, publisher = "Springer {\copyright}", series = "{\htmladdnormallink{LNCS}{http://www.springer.de/comp/lncs/index.html}}", } @InProceedings{DemSan03www, author = "R. Dementiev and P. Sanders", title = "\htmladdnormallink{Asynchronous Parallel Disk Sorting}{asyncsort.ps.gz}", booktitle = "15th ACM Symposium on Parallelism in Algorithms and Architectures", year = 2003, pages = "138--148", address = "San Diego", } @InProceedings{DemSan03, author = "R. Dementiev and P. Sanders", title = "Asynchronous Parallel Disk Sorting", booktitle = "15th ACM Symposium on Parallelism in Algorithms and Architectures", pages = "138--148", year = 2003, address = "San Diego", } %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Ich @Article{BecBelSan88, author = "B. Beckert and A. Bell and P. Sanders", title = "Gedichtgenerator --- {E}in {A}nwendungsbeispiel f{\"u}r nat{\"u}rlichsprachliche {T}exterzeugung", journal = "Junge Wissenschaft", year = 1988, volume = 3, number = 10, pages = "28--37" } @Manual{San88, title = "Benutzerhandbuch: Easy-{GEM} Library", organization = "Omikron Software", year = 1988 } @InCollection{BecBelSan90, author = "B. Beckert and A. Bell and P. Sanders", title = "Gedichtgenerator --- {E}in {A}nwendungsbeispiel f{\"u}r nat{\"u}rlichsprachliche {T}exterzeugung", booktitle = "Aus Neugier wird Wissenschaft -- Illustrierte Teilnehmerbeitr{\"a}ge aus 25 Jahren Jugend forscht", publisher = "Elektor Verlag", year = 1990 } @InCollection{BBS8890e, author = "B. Beckert and A. Bell and P. Sanders", title = "Gedichtgenerator --- {E}in {A}nwendungsbeispiel f{\"u}r nat{\"u}rlichsprachliche {T}exterzeugung", booktitle = "Aus Neugier wird Wissenschaft -- Illustrierte Teilnehmerbeitr{\"a}ge aus 25 Jahren Jugend forscht", publisher = "Elektor Verlag", note = "also in {\em Junge Wissenschaft}, 3(10):28--37, 1988", year = 1990 } @InCollection{BBS8890, author = "B. Beckert and A. Bell and P. Sanders", title = "Gedichtgenerator --- {E}in {A}nwendungsbeispiel f{\"u}r nat{\"u}rlichsprachliche {T}exterzeugung", booktitle = "Aus Neugier wird Wissenschaft -- Illustrierte Teilnehmerbeitr{\"a}ge aus 25 Jahren Jugend forscht", publisher = "Elektor Verlag", note = "auch in {\em Junge Wissenschaft}, 3(10):28--37, 1988", year = 1990 } @InCollection{San90, author = "P. Sanders", title = "Mr.\ {L}ine lernt {S}chreiben --- {G}rafiktexte mit {{\tt TXTGRA}}", booktitle = "Die Grafik-Connection", publisher = "Heim Verlag", year = 1990, editor = "S. Egner and M. Sperber", pages = "131--154" } @InProceedings{San93b, author = "P. Sanders", title = "A Case Study in Object Oriented Programming: Algebraic Data Structures in {E}iffel", editor = "R. Ege and M. Singh and B. Meyer", number = 11, series = "TOOLS", pages = "379--388", booktitle = "Technology of Object-Oriented Languages and Systems", year = 1993, publisher = "Prentice Hall", address = "Santa Barbara" } @Unpublished{San91, author = "P. Sanders", title = "Unifikation im typisierten {$\lambda$-Kalk\"ul --- Objektorientierte Implementation und Erweiterung um AC-Unifikation und Polymorphismus}", note = "Studienarbeit am FZI-Karlsruhe bei Prof. G. Goos und F. Weber", year = 1991 } @InProceedings{San93bwww, author = "P. Sanders", title = "{\htmladdnormallink{A Case Study in Object Oriented Programming: Algebraic Data Structures in {E}iffel}{algebra.ps.gz}}", editor = "R. Ege and M. Singh and B. Meyer", number = 11, series = "TOOLS", pages = "379--388", booktitle = "Technology of Object-Oriented Languages and Systems", year = 1993, publisher = "Prentice Hall", address = "Santa Barbara" } @MastersThesis{San93amix, author = "P. Sanders", title = "{S}uchalgorithmen auf {SIMD}-{R}echnern -- {W}eitere {E}rgebnisse zu {P}olyautomaten", school = "University of Karlsruhe", type = "Diplomarbeit", year = 1993, month = "August" } @MastersThesis{San93ae, author = "P. Sanders", title = "{S}uchalgorithmen auf {SIMD}-{R}echnern -- {W}eitere {E}rgebnisse zu {P}olyautomaten", school = "University of Karlsruhe", year = 1993, month = "August" } @MastersThesis{San93a, author = "P. Sanders", title = "{S}uchalgorithmen auf {SIMD}-{R}echnern -- {W}eitere {E}rgebnisse zu {P}olyautomaten", school = "Universit{\"a}t Karlsruhe", type = "Diplomarbeit", year = 1993, month = "August" } @MastersThesis{San93awww, author = "P. Sanders", title = "{\htmladdnormallink{{S}uchalgorithmen auf {SIMD}-{R}echnern -- {W}eitere {E}rgebnisse zu {P}olyautomaten}{da.ps.gz}}", school = "Universit{\"a}t Karlsruhe", type = "Diplomarbeit", year = 1993, month = "August" } @InProceedings{San94awww, author = "P. Sanders", title = "{\htmladdnormallink{Emulating {MIMD} behavior on {SIMD} machines}{delft.ps.gz}}", booktitle = "International Conference Massively Parallel Processing Applications and Development", address = "Delft", pages = "313--321", year = 1994, publisher = "Elsevier" } @InProceedings{San94a, author = "P. Sanders", title = "Emulating {MIMD} behavior on {SIMD} machines", booktitle = "International Conference Massively Parallel Processing Applications and Development", address = "Delft", pages = "313--321", year = 1994, publisher = "Elsevier" } @InProceedings{San94b, author = "P. Sanders", title = "Portable {p}arallele {B}aumsuchverfahren: {E}ntwurf {e}iner {e}ffizienten {B}ibliothek", booktitle = "Parallelrechner Anwender Treffen (TAT)", pages = "168--177", year = 1994, address = "Aachen", publisher = "IOS Press" } @InProceedings{San94bwww, author = "P. Sanders", title = "{\htmladdnormallink{Portable {p}arallele {B}aumsuchverfahren: {E}ntwurf {e}iner {e}ffizienten {B}ibliothek}{tat.ps.gz}}", booktitle = "Transputer Anwender Treffen", pages = "168--177", year = 1994, address = "Aachen", publisher = "IOS Press" } @InProceedings{San94c, author = "P. Sanders", title = "Massively Parallel Search for Transition-Tables of Polyautomata", booktitle = "Parcella 94, VI. International Workshop on Parallel Proccessing by Cellular Automata and Arrays", pages = "99--108", year = 1994, address = "Potsdam" } @InProceedings{San94cwww, author = "P. Sanders", title = "{\htmladdnormallink{Massively Parallel Search for Transition-Tables of Polyautomata}{parcella94.ps.gz}}", booktitle = "Parcella 94, VI. International Workshop on Parallel Proccessing by Cellular Automata and Array", pages = "99--108", year = 1994, address = "Potsdam" } @InProceedings{San94cs, author = "P. Sanders", title = "Massively Parallel Search for Transition-Tables of Polyautomata", booktitle = "VI. International Workshop on Parallel Proccessing by Cellular Automata and Arrays", year = 1994, } @InProceedings{San94cswww, author = "P. Sanders", title = "{\htmladdnormallink{Massively Parallel Search for Transition-Tables of Polyautomata}{parcella94.ps.gz}}", booktitle = "VI. International Workshop on Parallel Proccessing by Cellular Automata and Arrays", year = 1994, } @Article{Fly66, author = "M. Flynn", year = "1966", title = "Very High Speed Computing", journal = "Proceedings of the IEEE", pages = "1901--1909", kwds = "prll, simd, mimd, sisd", } @TechReport{San94d, author = "P. Sanders", title = "Analysis of Random Polling Dynamic Load Balancing", institution = "Universit{\"a}t Karlsruhe, Fakult{\"a}t f{\"u}r Informatik", year = 1994, number = "IB 12/94", month = "April" } @Article{Alo03, author = "N. Alon", title = "A simple algorithm for edge-coloring bipartite multigraphs", journal = "Information Processing Letters", year = 2003, volume = 85, pages = "301--302" } @TechReport{NAlon87, author = "N. Alon and B. Schieber", title = "Optimal preprocessing for answering on-line product queries", institution = "Tel Aviv University", year = 1987, number = "TR 71/87" } @TechReport{San94dwww, author = "P. Sanders", title = "{\htmladdnormallink{Analysis of Random Polling Dynamic Load Balancing}{trrp.ps.gz}}", institution = "Universit{\"a}t Karlsruhe, Fakult{\"a}t f{\"u}r Informatik", year = 1994, number = "IB 12/94", month = "April" } @InProceedings{San94e, author = "P. Sanders", title = "Flaschenhalsfreie parallele {P}riority queues", number = 13, series = "PARS Mitteilungen", booktitle = "PARS Workshop, Potsdam", pages = "10--19", month = "September", year = "1994" } @InProceedings{San94ewww, author = "P. Sanders", title = "{\htmladdnormallink{Flaschenhalsfreie parallele {P}riority queues}{pars94.ps.gz}}", number = 13, series = "PARS Mitteilungen", booktitle = "PARS Workshop, Potsdam", pages = "10--19", month = "September", year = "1994", note = "Improved results in Irregular'95 and JPDC" } @InProceedings{San94f, author = "P. Sanders", title = "Randomized static load balancing for tree shaped computations", series = "TR Universit{\"a}t Clausthal", pages = "58--69", issn = "0943-3805", note = "ISSN 0943-3805", booktitle = "Workshop on Parallel Processing", year = "1994", address = "Lessach, {\"O}sterreich" } @InProceedings{San94fwww, author = "P. Sanders", title = "{\htmladdnormallink{Randomized static load balancing for tree shaped computations}{lessach.ps.gz}}", series = "TR Universit{\"a}t Clausthal", pages = "58--69", issn = "0943-3805", note = "ISSN 0943-3805", booktitle = "Workshop on Parallel Processing", year = "1994", address = "Lessach, {\"O}sterreich" } @InProceedings{San94fjb, author = "P. Sanders", title = "Randomized static load balancing for tree shaped computations", editor = "K. Ecker and J. Aspel", number = "95/1", series = "Informatik-Bericht", pages = "58--69", issn = "0943-3805", OPTbooktitle = "Workshop {\"u}ber Parallelverarbeitung", year = 1995, OPTpublisher = "Universit{\"a}t Clausthal", OPTaddress = "Lessach, {\"O}sterreich", month = "September 1994" } @InProceedings{San94fe, author = "P. Sanders", title = "Randomized static load balancing for tree shaped computations", series = "TR University of Clausthal", number = "95/1", issn = "0943-3805", booktitle = "Workshop on Parallel Processing", year = 1994, address = "Lessach, Austria" } @InProceedings{San94g, author = "P. Sanders", title = "A Detailed Analysis of Random Polling Dynamic Load Balancing", booktitle = "International Symposium on Parallel Architectures, Algorithms and Networks", year = 1994, pages = "382--389", address = "Kanazawa, Japan", publisher = "IEEE, Los Alamitos, CA" } @InProceedings{San94gwww, author = "P. Sanders", title = "{\htmladdnormallink{A Detailed Analysis of Random Polling Dynamic Load Balancing}{ispan.ps.gz}}", booktitle = "International Symposium on Parallel Architectures, Algorithms and Networks", year = 1994, pages = "382--389", address = "Kanazawa, Japan" } @Unpublished{San94he, author = "P. Sanders", title = "Efficient emulation of {MIMD} behavior on {SIMD} machines", note = "submitted for publication", year = 1994, month = "August" } @TechReport{San95e, author = "P. Sanders", title = "Efficient emulation of {MIMD} behavior on {SIMD} machines", institution = "Universit{\"a}t Karlsruhe, Fakult{\"a}t f{\"u}r Informatik", year = 1995, number = "IB 29/95" } @TechReport{San95ee, author = "P. Sanders", title = "Efficient emulation of {MIMD} behavior on {SIMD} machines", institution = "University of Karlsruhe, Department of Computer Science", year = 1995, number = "IB 29/95" } @TechReport{San95a, author = "P. Sanders", title = "Towards Better Algorithms for Parallel Backtracking", institution = "Universit{\"a}t Karlsruhe, Fakult{\"a}t f{\"u}r Informatik", year = 1995, number = "IB 6/95", month = "Jan" } @InProceedings{San95b, author = "P. Sanders", title = "Better Algorithms for Parallel Backtracking", series = "LNCS", number = "980", pages = "333--347", booktitle = "Workshop on Algorithms for Irregularly Structured Problems", year = 1995, publisher = "Springer-Verlag Berlin", address = "Lyon, France, 4--6 September" } @InProceedings{San95bwww, author = "P. Sanders", title = "{\htmladdnormallink{Better Algorithms for Parallel Backtracking}{shuffleeabs.ps.gz}}", series = "{\htmladdnormallink{LNCS}{http://www.springer.de/comp/lncs/index.html}}", number = "980", pages = "333--347", booktitle = "Workshop on Algorithms for Irregularly Structured Problems", year = 1995, publisher = "Springer {\copyright}", address = "Lyon", note = "{\htmladdnormallink{Extended version}{shufflefull.ps.gz}}" } @InProceedings{San95bs, author = "P. Sanders", title = "Better Algorithms for Parallel Backtracking", series = "LNCS", number = "980", pages = "333--347", booktitle = "Workshop on Algorithms for Irregularly Structured Problems", year = 1995 } @InProceedings{San95cwww, author = "P. Sanders", title = "Fast Priority Queues for Parallel Branch-and-Bound", series = "{\htmladdnormallink{LNCS}{http://www.springer.de/comp/lncs/index.html}}", number = "980", pages = "379--393", booktitle = "Workshop on Algorithms for Irregularly Structured Problems", year = 1995, publisher = "Springer {\copyright}", address = "Lyon", note = "Improved version in JPDC, {\htmladdnormallink{extended version}{http://www.mpi-sb.mpg.de/{\%7e}anders/papers/1997-7.ps.gz}}" } @InProceedings{San95c, author = "P. Sanders", title = "Fast Priority Queues for Parallel Branch-and-Bound", series = "LNCS", number = "980", pages = "379--393", booktitle = "Workshop on Algorithms for Irregularly Structured Problems", year = 1995, publisher = "Springer", address = "Lyon" } @InProceedings{HopSan95, author = "H. Hopp and P. Sanders", title = "Parallel Game Tree Search on {SIMD} Machines", series = "LNCS", number = "980", pages = "349--361", booktitle = "Workshop on Algorithms for Irregularly Structured Problems", year = 1995, publisher = "Springer", address = "Lyon" } @InProceedings{HopSan95www, author = "H. Hopp and P. Sanders", title = "{\htmladdnormallink{Parallel Game Tree Search on {SIMD} Machines}{gamet.ps.gz}}", series = "{\htmladdnormallink{LNCS}{http://www.springer.de/comp/lncs/index.html}}", number = "980", pages = "349--361", booktitle = "Workshop on Algorithms for Irregularly Structured Problems", year = 1995, publisher = "Springer {\copyright}", address = "Lyon", note = "{\htmladdnormallink{Holger Hopp's Diploma thesis}{http://wwwipd.ira.uka.de/{\%7e}hopp/gts/dipl.ps.gz}} (in German), University of Karlsruhe, 1995. " } @Unpublished{San95d, author = "P. Sanders", title = "A Scalable Parallel Tree Search Library", note = "SuParCup '95", year = 1995 } @TechReport{San95f, author = "P. Sanders", title = "Some Implementation Results on Random Polling Dynamic Load Balancing", institution = "Universit{\"a}t Karlsruhe, Fakult{\"a}t f{\"u}r Informatik", year = 1995, number = "40/95", month = "August" } @InProceedings{San96a, author = "P. Sanders", title = "On the Competitive Analysis of Randomized Static Load Balancing", booktitle = "First Workshop on Randomized Parallel Algorithms", editor = "S. Rajasekaran", year = 1996, address = "Honolulu, Hawaii, 16 April" } @InProceedings{San96awww, author = "P. Sanders", title = "{\htmladdnormallink{On the Competitive Analysis of Randomized Static Load Balancing}{rand96.ps.gz}}", booktitle = "First Workshop on Randomized Parallel Algorithms", editor = "S. Rajasekaran", year = 1996, address = "Honolulu, Hawaii, 16 April" } @InProceedings{San96ahab, author = "P. Sanders", title = "On the Competitive Analysis of Randomized Static Load Balancing", booktitle = "First Workshop on Randomized Parallel Algorithms", editor = "S. Rajasekaran", year = 1996, address = "Honolulu, Hawaii, 16 April", note = "{\url{http://www.mpi-sb.mpg.de/~sanders/papers/rand96.ps.gz}}" } @InProceedings{San96b, author = "P. Sanders", title = "A Scalable Parallel Tree Search Library", booktitle = "2nd Workshop on Solving Irregular Problems on Distributed Memory Machines", year = 1996, note = "{\url{http://www.mpi-sb.mpg.de/~sanders/papers/irreg96.ps.gz}}", editor = "S. Ranka", address = "Honolulu, Hawaii, 16 April" } @InProceedings{San96bwww, author = "P. Sanders", title = "{\htmladdnormallink{A Scalable Parallel Tree Search Library}{irreg96.ps.gz}}", booktitle = "2nd Workshop on Solving Irregular Problems on Distributed Memory Machines", year = 1996, editor = "S. Ranka", address = "Honolulu, Hawaii" } @InProceedings{San96bhab, author = "P. Sanders", title = "{\htmladdnormallink{A Scalable Parallel Tree Search Library}{irreg96.ps.gz}}", booktitle = "2nd Workshop on Solving Irregular Problems on Distributed Memory Machines", year = 1996, editor = "S. Ranka", address = "Honolulu, Hawaii", note = "{\url{http://www.mpi-sb.mpg.de/~sanders/papers/irreg96.ps.gz}}" } @Article{DGKS96, author = "O. Devillers and M. Golin and K. Kedem and S. Schirra", title = "Queries on {V}oronoi Diagrams of Moving Points", journal = "Computational Geometry: Theory and Applications", year = 1996, volume = 6, pages = "315--327" } @Article{San00aboth, author = "P. Sanders", title = "Asynchronous Scheduling of Redundant Disk Arrays", journal = "IEEE Transactions on Computers", year = 2003, volume = 52, number = 9, pages = "1170--1184", note = "short version in 12th ACM Symposium on Parallel Algorithms and Architectures, pages 89--98, 2000" } @Article{San02a, author = "P. Sanders", title = "Asynchronous Scheduling of Redundant Disk Arrays", journal = "IEEE Transactions on Computers", year = 2003, volume = 52, number = 9, pages = "1170--1184", } @InProceedings{SET03www, author = "P. Sanders and S. Egner and L. Tolhuizen", title = "\htmladdnormallink{Polynomial Time Algorithms For Network Information Flow}{infoflow.ps.gz}", booktitle = "15th ACM Symposium on Parallel Algorithms and Architectures", year = 2003, pages = "286--294", } @InProceedings{SET03, author = "P. Sanders and S. Egner and L. Tolhuizen", title = "Polynomial Time Algorithms For Network Information Flow", booktitle = "15th ACM Symposium on Parallel Algorithms and Architectures", pages = "286--294", year = 2003, } @Unpublished{SET02www, author = "P. Sanders and S. Egner and L. Tolhuizen", title = "{\htmladdnormallink{Polynomial Time Algorithms For Network Information Flow}{incremental.ps}}", note = " ", month = "October", year = 2002 } @TechReport{KST02www, author = "I. Katriel and P. Sanders and J. L. Tr{\"a}ff", title = "{\htmladdnormallink{A Practical Minimum Spanning Tree Algorithm Using the Cycle Property}{primfilterTR.ps.gz}}", institution = "MPI Informatik, Germany", year = 2002, number = "MPI-I-2002-1-003", month = "October" } @TechReport{DemSan03a, author = "R. Dementiev and P. Sanders", title = "Asynchronous Parallel Disk Sorting", institution = "MPI Informatik, Germany", year = 2003, number = "MPI-I-2003-1-001" } @TechReport{KST02, author = "I. Katriel and P. Sanders and J. L. Tr{\"a}ff", title = "A Practical Minimum Spanning Tree Algorithm Using the Cycle Property", institution = "MPI Informatik, Germany", year = 2002, number = "MPI-I-2002-1-003", month = "October" } @InProceedings{KST03, author = "I. Katriel and P. Sanders and J. L. Tr{\"a}ff", title = "A Practical Minimum Spanning Tree Algorithm Using the Cycle Property", booktitle = "11th European Symposium on Algorithms (ESA)", year = 2003, publisher = "Springer", pages = "679--690", series = "LNCS", number = "2832" } @InProceedings{KST03www, author = "I. Katriel and P. Sanders and J. L. Tr{\"a}ff", title = "{\htmladdnormallink{A Practical Minimum Spanning Tree Algorithm Using the Cycle Property}{filter.ps.gz}}", booktitle = "11th European Symposium on Algorithms (ESA)", year = 2003, pages = "679--690", publisher = "Springer", series = "LNCS", number = "2832" } @TechReport{DGKS94, author = "O. Devillers and M. Golin and K. Kedem and S. Schirra", year = "1994", title = "Revenge of the Dog: Queries on {V}oronoi Diagrams of Moving Points", type = "Technical Report", number = "MPI-I-94-149", url = "ftp://ftp.mpi-sb.mpg.de/pub/papers/reports/MPI-I-94-149.ps.gz", institution = "Max-Planck-Institut f{\"u}r Informatik", address = "Saarbr{\"u}cken", annote = "submitted to Comp.Geom.:Theory and Appl.", abstract = "Suppose we are given $n$ moving postmen described by their motion equations $p_i(t) = s_i + v_it,$ $i=1,\ldots, n$, where $s_i \in \R^2$ is the position of the $i$'th postman at time $t=0$, and $v_i \in \R^2$ is his velocity . The problem we address is how to preprocess the postmen data so as to be able to efficiently answer two types of nearest neighbor queries. The first one asks ``who is the nearest postman at time $t_q$ to a dog located at point $s_q$. In the second type a fast query dog is located a point $s_q$ at time $t_q$, its velocity is $v_q$ where $v_q>|v_i|$ for all $i=1, \ldots , n$, and we want to know which postman the dog can catch first. We present two solutions to these problems. Both solutions use deterministic data structures.", } @Unpublished{San96cf, author = {P. Sanders}, title = {On the efficiency of nearest neighbor load balancing for random loads (extended version)}, note = {{\tt http://liinwww.ira.uka.de/$\sim$sanders/}}, year = 1996 } @InProceedings{San96c, author = "P. Sanders", title = "On the Efficiency of Nearest Neighbor Load Balancing for Random Loads", booktitle = "Parcella 96, VII. International Workshop on Parallel Proccessing by Cellular Automata and Arrays", year = 1996, pages = "120--127", publisher = "Akademie Verlag", address = "Berlin" } @InProceedings{San96cwww, author = "P. Sanders", title = "On the Efficiency of Nearest Neighbor Load Balancing for Random Loads", booktitle = "Parcella 96, VII. International Workshop on Parallel Proccessing by Cellular Automata and Arrays", year = 1996, pages = "120--127", publisher = "Akademie Verlag", address = "Berlin", note = "{\htmladdnormallink{Extended version}{diffuse.ps.gz}}" } @Unpublished{San96df, author = {P. Sanders}, title = {Optimizing the emulation of {MIMD} behavior on {SIMD} machines (extended version)}, note = {{\tt http://liinwww.ira.uka.de/$\sim$sanders/}}, year = 1996 } @InProceedings{San96d, author = "P. Sanders", title = "Optimizing the Emulation of {MIMD} Behavior on {SIMD} Machines", booktitle = "Parcella 96, VII. International Workshop on Parallel Proccessing by Cellular Automata and Arrays", year = 1996, publisher = "Akademie Verlag", address = "Berlin" } @InProceedings{San96dwww, author = "P. Sanders", title = "Optimizing the Emulation of {MIMD} Behavior on {SIMD} Machines", booktitle = "Parcella 96, VII. International Workshop on Parallel Proccessing by Cellular Automata and Arrays", year = 1996, publisher = "Akademie Verlag", address = "Berlin", note = "{\htmladdnormallink{Extended version}{simdp96.ps.gz}}" } @PhdThesis{San96ee, author = "P. Sanders", title = "Lastverteilungsalgorithmen f{\"u}r parallele Tiefensuche", school = "University of Karlsruhe", year = 1996 } @PhdThesis{San96e, author = "P. Sanders", title = "Lastverteilungsalgorithmen f{\"u}r parallele Tiefensuche", type = "Dissertation", school = "Universit{\"a}t Karlsruhe", year = 1996 } @Article{MehSan03, author = "K. Mehlhorn and P. Sanders", title = "Scanning Multiple Sequences Via Cache Memory", journal = "Algorithmica", year = 2003, volume = 35, number = 1, pages = "75--93", } @Book{San97a, author = "P. Sanders", title = "Load Balancing Algorithms for Parallel Depth First Search (In German: Lastverteilungsalgorithmen f{\"u}r parallele Tiefensuche)", publisher = "VDI Verlag, Berlin", isbn = "3-18-346310-5", year = 1997, number = 463, series = "Fortschrittsberichte, Reihe 10", } @PhdThesis{San97a-phd, author = "P. Sanders", title = "Lastverteilungsalgorithmen f{\"u}r parallele Tiefensuche", school = "University of Karlsruhe", year = 1997 } @TechReport{San97b, author = "P. Sanders", title = "Randomized Priority Queues for Fast Parallel Access", institution = "Universit{\"a}t Karlsruhe, Fakult{\"a}t f{\"u}r Informatik", year = "1997", number = "IB 7/97", } @TechReport{NieSan96, author = "R. Niedermeier and P. Sanders", title = "On the {M}anhattan-Distance Between Points on Space-Filling Mesh-Indexings", institution = "Universit{\"a}t Karlsruhe, Fakult{\"a}t f{\"u}r Informatik", year = 1996, number = "IB 18/96" } @TechReport{NieSan96e, author = "R. Niedermeier and P. Sanders", title = "On the {M}anhattan-Distance Between Points on Space-Filling Mesh-Indexings", institution = "University of Karlsruhe, Department of Computer Science", year = 1996, number = "IB 18/96" } @Article{NieReiSan02, author = "R. Niedermeier and K. Reinhard and P. Sanders", title = "Towards Optimal Locality in Mesh-Indexings", journal = "Discrete Applied Mathematics", volume = 117, pages = "211--237", month = "march", year = 2002, } @InProceedings{NieReiSan97, author = "R. Niedermeier and K. Reinhard and P. Sanders", title = "Towards Optimal Locality in Mesh-Indexings", booktitle = "Fundamentals of Computation Theory", editor = "B. S. Chlebus and L. Czaja", number = "1279", series = "LNCS", year = 1997, address = "Krakow", pages = "364--375" } @TechReport{NieReiSan97a, author = "R. Niedermeier and K. Reinhard and P. Sanders", title = "Towards Optimal Locality in Mesh-Indexings", institution = "University of Karlsruhe", year = 1997, number = "IB 12/97" } @InProceedings{SanSte05www, author = "P. Sanders and D. Steurer", title = "\htmladdnormallink{An Asymptotic Approximation Scheme for Multigraph Edge Coloring}{SanSte05.ps.gz}", booktitle = "16th ACM-SIAM Symposium on Discrete Algorithms", year = 2005 } @Unpublished{SS04www, author = "P. Sanders and D. Steurer", title = "\htmladdnormallink{An Asymptotic Approximation Scheme for Multigraph Edge Coloring}{edgecoloring.ps.gz}", note = "submitted for publication", month = "July", year = 2004 } @InProceedings{SanTra02www, author = "Sanders, Peter and Tr{\"a}ff, Jesper Larsson", title = "The Factor Algorithm for Regular All-to-all Communication on Clusters of {SMP} Nodes", booktitle = "8th Europar", publisher = "Springer {\copyright}", number = 2400, pages = "799--803", year = 2002, series = "{\htmladdnormallink{LNCS}{http://www.springer.de/comp/lncs/index}}", note = "{\htmladdnormallink{full paper}{europar2.ps.gz}}" } @Article{RST01, author = "R. Reussner and P. Sanders and J. Tr{\"a}ff", title = "{SKaMPI}: A Comprehensive Benchmark for Public Benchmarking of {MPI}", journal = "Scientific Programming", year = 2001, volume = 10, number = 1, pages = "55--65", } @InProceedings{SanTra02, author = "Sanders, Peter and Tr{\"a}ff, Jesper Larsson", title = "The Factor Algorithm for regular All-to-all Communication on Clusters of {SMP} Nodes", booktitle = "8th Europar", year = 2002, series = "LNCS", number = 2400, pages = "799--803", publisher = "Springer", } @Article{NieReiSan00www, author = "R. Niedermeier and K. Reinhard and P. Sanders", title = "Towards Optimal Locality in Mesh-Indexings", journal = "Discrete Applied Mathematics", volume = 117, number = "1--3", pages = "211--237", year = 2002, } @Unpublished{NieReiSan97d, author = "R. Niedermeier and K. Reinhard and P. Sanders", title = "Towards Optimal Locality in Mesh-Indexings", year = 1996, note = "Zur Ver{\"o}ffentlichung eingereicht" } @Unpublished{San97x, author = "P. Sanders", title = "High Performance Computing Aspects of Airline Crew Scheduling Optimization", note = "working paper", year = 1997, month = "October", annote = "Abschlussaufschrieb in Goeteborg" } @InProceedings{NieReiSan97www, author = "R. Niedermeier and K. Reinhard and P. Sanders", title = "Towards Optimal Locality in Mesh-Indexings", booktitle = "Fundamentals of Computation Theory", editor = "B. S. Chlebus and L. Czaja", number = "1279", series = "{\htmladdnormallink{LNCS}{http://www.springer.de/comp/lncs/index.html}}", year = 1997, address = "Krakow", pages = "364--375", note = "{\htmladdnormallink{Extended version}{1997-12.ps.gz}} as Technical Report IB 12/97, University of Karlsruhe, 1997" } @Unpublished{NieReiSan98, author = "R. Niedermeier and K. Reinhard and P. Sanders", title = "Towards Optimal Locality in Mesh-Indexings", note = "{\url{http://www.mpi-sb.mpg.de/~sanders/papers/1997-12.ps.gz}}" } @InProceedings{SanHan97e, author = "P. Sanders and T. Hansch", title = "On the Efficient Implementation of Massively Parallel Quicksort", booktitle = "4th International Symposium on Solving Irregularly Structured Problems in Parallel", editor = "G. Bilardi and A. Ferreira and R. L{\"u}ling and J. Rolim", number = 1253, series = "LNCS", issn = "0302-9743", year = 1997, pages = "13--24", publisher = "Springer" } @InProceedings{SanHan97ewww, author = "P. Sanders and T. Hansch", title = "{\htmladdnormallink{On the Efficient Implementation of Massively Parallel Quicksort}{qsort.ps.gz}}", booktitle = "4th International Symposium on Solving Irregularly Structured Problems in Parallel", number = 1253, series = "{\htmladdnormallink{LNCS}{http://www.springer.de/comp/lncs/index.html}}", year = 1997, pages = "13--24", publisher = "Springer {\copyright}", note = "Thomas Hansch's {\htmladdnormallink{Diploma thesis}{Han97.ps.gz}} (in German), University of Karlsruhe, 1996. {\htmladdnormallink{Complete set of data sheets (English translation)}{Han97data.ps.gz}}" } @Unpublished{SanHan97d, author = "P. Sanders and T. Hansch", title = "On the Efficient Implementation of Massively Parallel Quicksort", note = "Zur Ver{\"o}ffentlichung eingereicht", year = 1996 } @InProceedings{SanWor95, author = "P. Sanders and T. Worsch", title = "Konvergente lokale {L}astverteilungsverfahren und ihre {M}odellierung durch {Z}ellularautomaten", number = 14, series = "PARS Mitteilungen", pages = "285--291", booktitle = "PARS Workshop", year = 1995 } @InProceedings{SanWor95www, author = "P. Sanders and T. Worsch", title = "{\htmladdnormallink{Konvergente lokale {L}astverteilungsverfahren und ihre {M}odellierung durch {Z}ellularautomaten}{pars95.ps.gz}}", number = 14, series = "PARS Mitteilungen", pages = "285--291", booktitle = "PARS Workshop", year = 1995 } @Unpublished{SanWor96, author = "P. Sanders and T. Worsch", title = "Praktikum nachrichtengekoppelte Parallelrechner mit MPI", note = "Praktikumsunterlagen, Universit{\"a}t Karlsruhe", year = 1996 } @Book{SanWor97, author = "P. Sanders and T. Worsch", title = "Parallele Programmierung mit MPI -- ein Praktikum", publisher = "Logos Verlag Berlin", year = 1997, note = "ISBN 3-931216-76-4" } @Book{SanWor97vorl, author = "P. Sanders and T. Worsch", title = "Parallele Programmierung mit MPI -- ein Praktikum", publisher = "Logos Verlag Berlin", year = 1997, note = "f{\"u}r Leute, die etwas zur Vorlesung programmieren m{\"o}chten" } @Book{SanWor97www, author = "P. Sanders and T. Worsch", title = "{\htmladdnormallink{Parallele Programmierung mit MPI -- ein Praktikum}{http://liinwww.ira.uka.de/mpibook/}}", publisher = "Logos Verlag Berlin", year = 1997, note = "ISBN 3-931216-76-4" } @TechReport{BSP97, author = "J. M. D. Hill et al.", title = "BSPlib: The BSP Programming Library", institution = "Oxford University Computing Laboratory", year = 1997, number = "PRG-TR-29-97", note = "{\url{http://www.BSP-Worldwide.org/implmnts/oxtool/}}" } @InProceedings{PUB99, author = "O. Bonorden and B. Juurlink and I. von Otte and I. Rieping", title = "The Paderborn University BSP (PUB) Library - Design, Implementation and Performance", booktitle = "IPPS/SPDP", year = 1999, note = "{\url{http://www.uni-paderborn.de/~pub/}}" } @InProceedings{RSPM98link, author = "R. Reussner and P. Sanders and L. Prechelt and M. M{\"u}ller", title = "{SKaMPI}: A Detailed, Accurate {MPI} Benchmark", number = "1497", series = "LNCS", pages = "52--59", booktitle = "EuroPVM/MPI see also {\url{http://liinwww.ira.uka.de/~skampi/}}", year = 1998 } @InProceedings{RSPM98, author = "R. Reussner and P. Sanders and L. Prechelt and M. M{\"u}ller", title = "{SKaMPI}: A Detailed, Accurate {MPI} Benchmark", number = "1497", series = "LNCS", pages = "52--59", booktitle = "EuroPVM/MPI", year = 1998 } @InProceedings{RSPM98www, author = "R. Reussner and P. Sanders and L. Prechelt and M. M{\"u}ller", title = "{\htmladdnormallink{SKaMPI: A Detailed, Accurate MPI Benchmark}{europvm-mpi98.ps.gz}}", number = "1497", series = "{\htmladdnormallink{LNCS}{http://www.springer.de/comp/lncs/index.html}}", pages = "52--59", booktitle = "EuroPVM/MPI", year = 1998, note = "\htmladdnormallink{(SKaMPI Home Page)}{http://wwwipd.ira.uka.de/{\%7e}skampi/}" } @Article{San98c, author = "P. Sanders", title = "Random Permutations on Distributed, External and Hierarchical Memory", volume = 67, number = 6, journal = "Information Processing Letters", pages = "305--310", year = 1998, } @Unpublished{Han95a, author = "T. Hansch", title = "Segmentierte kollektive {O}perationen auf {G}ittern mit {H}ilbertnumerierung", note = "Studienarbeit", year = 1995 } @Unpublished{Han96, author = "T. Hansch", title = "Sortieren gro{\ss}er {D}atenmengen auf {G}ittern mit {Q}uicksort", note = "Diplomarbeit", year = 1996 } @MastersThesis{Hop95, author = "H. Hopp", title = "Parallele {S}pielbaumsuche auf {SIMD}-{R}echnern", school = "Universit{\"a}t Karlsruhe", year = 1995, type = "Diplomarbeit" } @Manual{DieSan95, title = "PIGSel Manual", author = "P. Diefenbach and P. Sanders", organization = "Universit{\"a}t Karlsruhe, LIIN", year = 1995 } @MastersThesis{Die96e, author = "P. Diefenbach", title = "Lastverteilung mit {V}erdr{\"a}ngung in parallelen {S}pielbaumsuchverfahren auf {MIMD}-{R}echnern", school = "University of Karlsruhe", year = 1996, } @TechReport{SanVolWor97a, AUTHOR = "Peter Sanders and Roland Vollmar and Thomas Worsch", TITLE = "Feasible Models of Computation: Three-Dimensionality and Energy Consumption", INSTITUTION = "Universit{\"a}t Karlsruhe, Fakult{\"a}t f{\"u}r Informatik", YEAR = "1997", type = "Technical report", number = "2/97", } @InProceedings{SanVolWor97b, author = "Peter Sanders and Roland Vollmar and Thomas Worsch", title = "Feasible Models of Computation: Three-Dimensionality and Energy Consumption", editor = "C. Lengauer and M. Griebl and S. Gorlatch", number = 1300, series = "LNCS", pages = "384--388", booktitle = "Euro-Par", year = 1997, publisher = "Springer", address = "Passau" } @InProceedings{SanVolWor97bwww, author = "Peter Sanders and Roland Vollmar and Thomas Worsch", title = "Feasible Models of Computation: Three-Dimensionality and Energy Consumption", editor = "C. Lengauer and M. Griebl and S. Gorlatch", number = 1300, note = "{\htmladdnormallink{Extended version}{1997-2.ps.gz}} as Technical Report IB 2/97, University of Karlsruhe, 1997", series = "LNCS", pages = "384--388", booktitle = "Euro-Par", year = 1997, publisher = "Springer {\copyright}", address = "Passau" } @Article{SanVolWor00, author = "P. Sanders and R. Vollmar and T. Worsch", title = "Feasible Models of Computation: Three-Dimensionality and Energy Consumption", journal = "Fundamenta Informaticae", year = 2002, volume = 52, number = "1--3", pages = "233--248" } @InProceedings{SanVolWor97bfullurl, author = "Peter Sanders and Roland Vollmar and Thomas Worsch", title = "Feasible Models of Computation: Three-Dimensionality and Energy Consumption", editor = "C. Lengauer and M. Griebl and S. Gorlatch", number = 1300, note = "{\htmladdnormallink{Extended version}{http://www.mpi-sb.mpg.de/{\%7e}sanders/papers/1997-2.ps.gz}} as Technical Report IB 2/97, University of Karlsruhe, 1997", series = "LNCS", pages = "384--388", booktitle = "Euro-Par", year = 1997, publisher = "Springer {\copyright}", address = "Passau" } @Unpublished{San98d, author = "P. Sanders", title = "Randomized Receiver Initiated Load Balancing Algorithms for Tree Shaped Computations", year = 1998 } @Unpublished{San98dwww, author = "P. Sanders", title = "\htmladdnormallink{Randomized Receiver Initiated Load Balancing Algorithms for Tree Shaped Computations}{submit.ps.gz}", note = "submitted for publication", year = 1998 } @Unpublished{San98dsub, author = "P. Sanders", title = "Randomized Receiver Initiated Load Balancing Algorithms for Tree Shaped Computations", note = "{\url{http://www.mpi-sb.mpg.de/~sanders/papers/submit.ps.gz}}", year = 1998 } @Article{San98a, author = "P. Sanders", title = "Randomized Priority Queues for Fast Parallel Access", volume = 49, pages = "86--97", journal = "Journal Parallel and Distributed Computing, Special Issue on Parallel and Distributed Data Structures", year = 1998, } @Article{San98awww, author = "P. Sanders", title = "Randomized Priority Queues for Fast Parallel Access", volume = 49, pages = "86--97", journal = "Journal Parallel and Distributed Computing, Special Issue on Parallel and Distributed Data Structures", year = 1998, note = "{\htmladdnormallink{Extended version}{1997-7.ps.gz}}" } @Article{San98a-s, author = "P. Sanders", title = "Randomized Priority Queues for Fast Parallel Access", volume = 49, pages = "86--97", journal = "Journal Parallel and Distributed Computing", year = 1998, } @Article{San98a-e, author = "P. Sanders", title = "Randomized Priority Queues for Fast Parallel Access", journal = "Journal Parallel and Distributed Computing, Special Issue on Parallel and Distributed Data Structures", year = 1998, note = "to appear, extended version: \url{http://www.mpi-sb.mpg.de/~sanders/papers/1997-7.ps.gz}" } @TechReport{AKE00, author = "J. Aerts and J. Korst and S. Egner", title = "Random duplicate storage strategies for load balancing in multimedia servers", institution = "Philips Research Laboratories", year = 2000, number = "NL-MS 20.314" } @InProceedings{SanEgnKor00, author = "P. Sanders and S. Egner and J. Korst", title = "Fast Concurrent Access to Parallel Disks", booktitle = "11th ACM-SIAM Symposium on Discrete Algorithms", year = 2000, pages = "849--858", } @InProceedings{SGNG00, author = "S. W. Schlosser and J. L. Griffin and D. F. Nagle and G. R. Ganger", title = "Designing Computer Systems with {MEMS}-based Storage", booktitle = "9th International Conference on Architectural Support for Programming Languages and Operating Systems", pages = "1--12", note = "SIGPLAN Notices 35(11)", year = 2000, annote = "propesed to go between main memory and disks" } @Unpublished{San00c, author = "P. Sanders", title = "Asynchronous Scheduling of Redundant Disk Arrays", note = "{\url{http://www.mpi-sb.mpg.de/~sanders/papers/spaa00-full.ps.gz}}" } @InProceedings{San00aalcom, author = "P. Sanders", title = "Asynchronous Scheduling of Redundant Disk Arrays", booktitle = "12th ACM Symposium on Parallel Algorithms and Architectures", year = 2000, note = "also report ALCOMFT-TR-01-99", pages = "89--98", } @InProceedings{San00awww, author = "P. Sanders", title = "\htmladdnormallink{Asynchronous Scheduling of Redundant Disk Arrays}{asyncpardisk.ps.gz}", booktitle = "12th ACM Symposium on Parallel Algorithms and Architectures", year = 2000, pages = "89--98", } @InProceedings{San00a, author = "P. Sanders", title = "Asynchronous Scheduling of Redundant Disk Arrays", booktitle = "12th ACM Symposium on Parallel Algorithms and Architectures", year = 2000, pages = "89--98", } @Unpublished{SanEgnKor00b, author = "P. Sanders and S. Egner and J. Korst", title = "Fast Concurrent Access to Parallel Disks", note = "{\url{http://www.mpi-sb.mpg.de/~sanders/papers/full-pardisk.ps.gz}}" } @InProceedings{SanEgnKor00www, author = "P. Sanders and S. Egner and J. Korst", title = "\htmladdnormallink{Fast Concurrent Access to Parallel Disks}{soda00.ps.gz}", booktitle = "11th ACM-SIAM Symposium on Discrete Algorithms", pages = "849--858", year = 2000, note = "{\htmladdnormallink{full paper}{full-pardisk.ps.gz}}" } @Unpublished{SanSib00a, author = "P. Sanders and J. Sibeyn", title = "A Bandwidth Latency Tradeoff for Broadcast and Reduction", note = "{\url{http://www.mpi-sb.mpg.de/~sanders/papers/ipl.ps.gz}}", year = 2000 } @InProceedings{SanSib00, author = "P. Sanders and J. Sibeyn", title = "A Bandwidth Latency Tradeoff for Broadcast and Reduction", booktitle = "6th Euro-Par", number = 1900, series = "LNCS", pages = "918--926", year = 2000, } @Article{SanSib02, author = "P. Sanders and J. Sibeyn", title = "A Bandwidth Latency Tradeoff for Broadcast and Reduction", journal = "Information Processing Letters", year = 2003, volume = 86, pages = "33--38", number = 1, } @InProceedings{SanSib00www, author = "P. Sanders and J. Sibeyn", title = "{\htmladdnormallink{A Bandwidth Latency Tradeoff for Broadcast and Reduction}{bcast.ps.gz}}", series = "{\htmladdnormallink{LNCS}{http://www.springer.de/comp/lncs/index.html}}", publisher = "Springer {\copyright}", booktitle = "6th Euro-Par", number = 1900, pages = "918--926", year = 2000, } @InProceedings{MeySan00www, author = "U. Meyer and P. Sanders", title = "{\htmladdnormallink{Parallel Shortest Path for Arbitrary Graphs}{spath00.ps.gz}}", series = "{\htmladdnormallink{LNCS}{http://www.springer.de/comp/lncs/index.html}}", publisher = "Springer {\copyright}", booktitle = "6th Euro-Par", number = 1900, pages = "461--470", year = 2000, } @InProceedings{MeySan00, author = "U. Meyer and P. Sanders", title = "Parallel Shortest Path for Arbitrary Graphs", booktitle = "6th Euro-Par", series = "LNCS", number = 1900, pages = "461--470", year = 2000, } @Unpublished{SanSol00a, author = "P. Sanders and R. Solis-Oba", title = "How Helpers Hasten $h$-Relations", note = "{\url{http://www.mpi-sb.mpg.de/~sanders/papers/allall9.ps.gz}}" } @Article{SanSol01, author = "P. Sanders and R. Solis-Oba", title = "How Helpers Hasten $h$-Relations", journal = "Journal of Algorithms", year = 2001, volume = 41, pages = "86--98", } @InProceedings{SanSol00, author = "P. Sanders and R. Solis-Oba", title = "How Helpers Hasten $h$-Relations", booktitle = "8th European Symposium on Algorithms (ESA)", publisher = "Springer {\copyright}", series = "LNCS", year = 2000, number = 1879, pages = "392--402", } @InProceedings{SanSol00www, author = "P. Sanders and R. Solis-Oba", title = "\htmladdnormallink{How Helpers Hasten $h$-Relations}{esa00.ps.gz}", booktitle = "8th European Symposium on Algorithms (ESA)", series = "{\htmladdnormallink{LNCS}{http://www.springer.de/comp/lncs/index.html}}", year = 2000, number = 1879, pages = "392--402", note = "{\htmladdnormallink{final paper}{allall10.ps.gz}}" } @Article{San01c, author = "P. Sanders", title = "Reconciling Simplicity and Realism in Parallel Disk Models", journal = "Parallel Computing", year = 2002, volume = 28, number = 5, pages = "705--723", note = "Special Issue on Parallel Data Intensive Algorithms and Applications" } @Article{San01cboth, author = "P. Sanders", title = "Reconciling Simplicity and Realism in Parallel Disk Models", journal = "Parallel Computing", year = 2002, volume = 28, number = 5, pages = "705--723", note = "short version in 12th SODA, p. 67--76, 2001." } @TechReport{SanSol01a, author = "P. Sanders and R. Solis-Oba", title = "How helpers hasten $h$-relations", institution = "The University of Western Ontario, Department of Computer Science", year = 2001, number = "559", month = "March" } @InProceedings{FMS03, author = "S. Funke and D. Matijevic and P. Sanders", title = "Approximating Energy Efficient Paths in Multi-Hop Networks", booktitle = "11th European Symposium on Algorithms (ESA)", year = 2003, publisher = "Springer", series = "LNCS", number = "2832" } @InProceedings{FMS03www, author = "S. Funke and D. Matijevic and P. Sanders", title = "{\htmladdnormallink{Approximating Energy Efficient Paths in Multi-Hop Networks}{http://www.mpi-sb.mpg.de/~funke/RadioESA03long.ps.gz}}", booktitle = "11th European Symposium on Algorithms (ESA)", year = 2003, publisher = "Springer", series = "LNCS", number = "2832" } @InProceedings{BSS02, author = "R. Beier and P. Sanders and N. Sivadasan", title = "Energy Optimal Routing in Radio Networks Using Geometric Data Structures", booktitle = "29th International Colloquium on Automata, Languages and Programming", year = 2002, publisher = "Springer", number = 2380, pages = "366--376", } @InProceedings{BSS02www, author = "R. Beier and P. Sanders and N. Sivadasan", title = "{\htmladdnormallink{Energy Optimal Routing in Radio Networks Using Geometric Data Structures}{icalp02.ps.gz}}", booktitle = "29th International Colloquium on Automata, Languages and Programming", series = "{\htmladdnormallink{LNCS}{http://www.springer.de/comp/lncs/index}}", number = 2380, pages = "366--376", publisher = "Springer {\copyright}", year = 2002, } @Article{San00bwww, author = "P. Sanders", title = "{\htmladdnormallink{Fast Priority Queues for Cached Memory}{http://www.mpi-sb.mpg.de/{\%7e}sanders/papers/spqjea.ps.gz}}", journal = "ACM Journal of ExperimentalAlgorithmics", volume = 5, year = 2000, } @InProceedings{SanVoe02www, author = "P. Sanders and B. V{\"o}cking", title = "{\htmladdnormallink{Random Arc Allocation and Applications to Disks, Drums and DRAMs}{swat02.ps.gz}}", booktitle = "8th Scandinavian Workshop on Algorithm Theory", series = "{\htmladdnormallink{LNCS}{http://www.springer.de/comp/lncs/index}}", publisher = "Springer {\copyright}", number = 2368, pages = "121--130", year = 2002, note = "{\htmladdnormallink{full paper}{swat02full.ps.gz}}" } @PhdThesis{Ric94, author = "Ivan L. M. Ricarte", school = "University of Maryland College Park", title = "Performance and Scalability of Parallel Database Systems", year = "1994", abstract-url = "http://www.dca.fee.unicamp.br/~ricarte/Papers/papers.html#phddiss", address = "College Park, MD, USA", url = "ftp://ftp.dca.fee.unicamp.br/pub/docs/ricarte/papers/phddiss.ps.gz", keywords = "Parallel processing, relational databases, parallel external sorting, parallel join", month = jan, parallelissues = "defined", scope = "rel", } @Article{SanVoe03, author = "P. Sanders and B. V{\"o}cking", title = "Tail Bounds And Expectations For Random Arc Allocation And Applications", journal = "Combinatorics Probability and Computing", year = 2003, volume = 12, number = 3, pages = "301--318" } @InProceedings{SanVoe02, author = "P. Sanders and B. V{\"o}cking", title = "Random Arc Allocation and Applications", booktitle = "8th Scandinavian Workshop on Algorithm Theory", number = 2368, series = "LNCS", pages = "121--130", publisher = "Springer", year = 2001 } @InProceedings{San01aalcom, author = "P. Sanders", title = "Reconciling Simplicity and Realism in Parallel Disk Models", booktitle = "12th ACM-SIAM Symposium on Discrete Algorithms", year = 2001, note = "also report ALCOMFT-TR-01-82", address = "Washington DC", pages = "67--76" } @InProceedings{San01a, author = "P. Sanders", title = "Reconciling Simplicity and Realism in Parallel Disk Models", booktitle = "12th ACM-SIAM Symposium on Discrete Algorithms", year = 2001, address = "Washington DC", pages = "67--76" } @InProceedings{San01awww, author = "P. Sanders", title = "\htmladdnormallink{Reconciling Simplicity and Realism in Parallel Disk Models}{realism-short.ps}", booktitle = "12th ACM-SIAM Symposium on Discrete Algorithms", year = 2001, address = "Washington DC", pages = "67--76" } @InCollection{San01b, author = "P. Sanders", title = "Presenting Data from Experiments in Algorithmics", booktitle = "Experimental Algorithmics --- From Algorithm Design to Robust and Efficient Software", volume = 2547, series = "LNCS", pages = "181--196", publisher = "Springer", year = 2002, } @InCollection{San02bwww, author = "P. Sanders", title = "{\htmladdnormallink{Presenting Data from Experiments in Algorithmics}{mess.ps.gz}}", series = "{\htmladdnormallink{LNCS}{http://www.springer.de/comp/lncs/index}}", booktitle = "Experimental Algorithmics --- From Algorithm Design to Robust and Efficient Software", pages = "181--196", volume = 2547, publisher = "Springer {\copyright}", year = 2002, } @InProceedings{HagRam92, author = "T. Hagerup and R. Raman", title = "Waste makes haste: Tight bounds for loose parallel sorting", booktitle = "33rd IEEE Symposium on Foundations of Computing", pages = "628--637", year = 1992 } @InCollection{MSFCP02www, author = "C. McGeoch and P. Sanders and R. Fleischer and P. R. Cohen and D. Precup", title = "{\htmladdnormallink{Searching for Big-Oh in the Data: Inferring Asymptotic Complexity from Experiments}{bigoh.ps.gz}}", series = "{\htmladdnormallink{LNCS}{http://www.springer.de/comp/lncs/index}}", booktitle = "Experimental Algorithmics --- From Algorithm Design to Robust and Efficient Software", volume = 2547, publisher = "Springer {\copyright}", year = 2002, } @InCollection{MSFCP02, author = "C. McGeoch and P. Sanders and R. Fleischer and P. R. Cohen and D. Precup", title = "Using Finite Experiments to Study Asymptotic Performance", booktitle = "Experimental Algorithmics --- From Algorithm Design to Robust and Efficient Software", volume = 2547, pages = "1--23", series = "LNCS", publisher = "Springer", year = 2002, } @Article{KPH98, author = "K. Keeton and D. A. Patterson and J. M. Hellerstein", title = "A Case for Intelligent Disks ({IDISK}s)", journal = "SIGMOD Record", year = 1998, volume = 27, number = 3 } @InProceedings{HutSanVit01bwww, author = "D. A. Hutchinson and P. Sanders and J. S. Vitter", title = "{\htmladdnormallink{Duality Between Prefetching and Queued Writing with Parallel Disks}{esa01.ps.gz}}", booktitle = "9th European Symposium on Algorithms (ESA)", year = 2001, series = "{\htmladdnormallink{LNCS}{http://www.springer.de/comp/lncs/index.html}}", publisher = "Springer{\copyright}", number = 2161, pages = "62--73", } @InProceedings{HutSanVit01b, author = "D. A. Hutchinson and P. Sanders and J. S. Vitter", title = "Duality Between Prefetching and Queued Writing with Parallel Disks", booktitle = "9th European Symposium on Algorithms (ESA)", year = 2001, number = 2161, pages = "62--73", series = "LNCS", publisher = "Springer", } @Article{LYC02, author = "S.-Y. R. Li and R. W. Yeung and N. Cai", title = "Linear network coding", journal = "IEEE Transactions on Information Theory", year = 2003, pages = "371--381", volume = 49, number = 2, } @InProceedings{CaiYeu02, author = "N. Cai and R. W. Yeung", title = "Network coding and error correction.", booktitle = "Information Theory Workshop", pages = "119--122", year = 2002, address = "Bangalore" } @BOOK{McW88, AUTHOR = {MacWilliams, F.J. and Sloane, N.J.A.}, TITLE = {Theory of error-correcting codes}, PUBLISHER = {North-Holland}, YEAR = {1988}, PLACE = {Natlab-Bib, PB 151}, COMMENT = {Standardwerk ueber Codierungstheorie} } @TECHREPORT{GibEtAl88, AUTHOR = { Gibson, G. A. and Hellerstein, L. and Karp, R. M. and Katz, R. H. and Patterson, D. A. }, TITLE = { Coding Techniques for Handling Failures in Large Disk Arrays, {CSD}-88-477 }, YEAR = {1988}, INSTITUTION = {U. C. Berkley}, URL = {http://cs-tr.cs.berkeley.edu/TR/UCB:CSD-88-477}, COMMENT = { Use linear Maximum Distance Separable (MDS) codes to redundantly store data on disk arrays to protect the data against disk failure. } } @Unpublished{RasLehLeh, author = "A. Rasala~Lehman and E. Lehman.", title = "Complexity Classification of Network Information Flow Problems", note = "manuscript", month = "April", year = 2003, } @InProceedings{HoKMKE03, author = "T. Ho. and R. Koetter and M. M{\'e}dard and D. Karger, M. Effros", title = "The Benefits of Coding over Routing in a Randomized Setting", booktitle = "International Symposium on Information Theory", year = 2003 } @InProceedings{KoeMed02, author = "R. Koetter and M. Medard", title = "An Algebraic Approach to Network Coding", booktitle = "Proceedings of {INFOCOM}", year = 2002 } @Article{ACLY00, author = "R. Ahlswede and N. Cai and S.-Y. R. Li and R. W. Yeung", title = "Network Information Flow", journal = "IEEE Transactions on Information Theory", volume = "46", pages = "1204-1216", number = 4, year = "2000", } @InProceedings{HutSanVit01balcom, author = "D. A. Hutchinson and P. Sanders and J. S. Vitter", title = "Duality Between Prefetching and Queued Writing with Parallel Disks", booktitle = "9th European Symposium on Algorithms (ESA)", year = 2001, series = "LNCS", publisher = "Springer", note = "to appear, also report ALCOMFT-TR-01-79", } @InProceedings{HutSanVit01a, author = "D. A. Hutchinson and P. Sanders and J. S. Vitter", title = "The Power of Duality for Prefetching and Sorting with Parallel Disks", booktitle = "12th ACM Symposium on Parallel Algorithms and Architectures (SPAA Revue)", year = 2001, pages = "334--335" } @Unpublished{SedGon01, author = "A. Sedeno-Noda and C. Gonzales-Martin", title = "A Two-Phase Double Capacity-Scaling Algorithm to Solve the Maximum Flow Problem", note = " " } @InCollection{BadBor93, author = "T. Badics and E. Boros", title = "Implementing a Maximum Flow Algorithm: Experiments with Dynamic Trees", booktitle = "First {DIMACS} Implementation Challenge --- Network Flows and Matching", pages = "43--63", publisher = "DIMACS", year = 1993, volume = 12, series = "{DIMACS} Series in Discrete Mathematics and Theoretical Computer Science" } @InProceedings{Mey01, author = "U. Meyer", title = "Single-Source Shortest-Paths on Arbitrary Directed Graphs in Linear Average-Case Time", booktitle = "Proc. 12th Symposium on Discrete Algorithms", pages = "797--806", year = 2001 } 2.Meyer, U., Single-Source Shortest-Paths on Arbitrary Directed Graphs in Linear Average-Case Time Proc. 12th Symposium on Discrete Algorithms (SODA 2001), pp. 797-806, ACM-SIAM , 2001. @Article{GolRao98, author = "Andrew V. Goldberg and Satish Rao", title = "Beyond the flow decomposition barrier", journal = "Journal of the ACM", volume = "45", number = "5", pages = "1--15", month = sep, year = "1998", coden = "JACOAH", ISSN = "0004-5411", bibdate = "Wed Dec 16 07:11:23 MST 1998", url = "http://www.acm.org:80/pubs/citations/journals/jacm/1998-45-5/p1-goldberg/", abstract = "We introduce a new approach to the maximum flow problem. This approach is based on assigning arc lengths based on the residual flow value and the residual arc capacities. Our approach leads to an {\em O\/}(min({\em n\/}2/3, {\em m\/}1/2){\em m\/} log({\em n\/}2/{\em m\/}) log {\em U\/}) time bound for a network with {\em n\/} vertices, {\em m\/} arcs, and integral arc capacities in the range [1, ..., {\em U\/}]. This is a fundamental improvement over the previous time bounds. We also improve bounds for the Gomory-Hu tree problem, the parametric flow problem, and the approximate {\em s-t\/} cut problem.", acknowledgement = ack-nhfb, keywords = "algorithms", subject = "{\bf F.2.2} Theory of Computation, ANALYSIS OF ALGORITHMS AND PROBLEM COMPLEXITY, Nonnumerical Algorithms and Problems. {\bf G.2.2} Mathematics of Computing, DISCRETE MATHEMATICS, Graph Theory.", xxnote = "Check pages??", } @InProceedings{GolRao97, author = "A. V. Goldberg and S. Rao", title = "Beyond the Flow Decomposition Barrier", pages = "2--11", ISBN = "0-8186-8197-7", booktitle = "Proceedings of the 38th Annual Symposium on Foundations of Computer Science ({FOCS}-97)", month = oct # "20--22~", publisher = "IEEE Computer Society Press", address = "Los Alamitos", year = "1997", } @InProceedings{MehZie00, author = {K. Mehlhorn and M. Ziegelmann}, title = {Resource Constrained Shortest Paths}, booktitle = {7th Annual European Symposium on Algorithms (ESA2000), LNCS 1879}, pages = {326--337}, year = 2000 } @Article{Cheriyan:1996:TAM, author = "Joseph Cheriyan and Torben Hagerup and Kurt Mehlhorn", title = "An $o(n^3)$-Time Algorithm Maximum-Flow Algorithm", journal = "SIAM Journal on Computing", volume = "25", number = "6", pages = "1144--1170", month = dec, year = "1996", coden = "SMJCAT", ISSN = "0097-5397 (print), 1095-7111 (electronic)", mrclass = "90C35 (68Q22 68Q25 68R10)", mrnumber = "1 417 893", bibdate = "Sat Dec 5 17:26:53 MST 1998", url = "http://epubs.siam.org/sam-bin/dbq/article/27837", acknowledgement = ack-nhfb, xxtitle = "An $o(n^3)$-time maximum-flow algorithm", } @Unpublished{Hag98, author = "T. Hagerup", title = "Goldberg and Rao's New Maxumum-Flow Algoirthm", note = "MPII noon seminar", year = 1997 } @Unpublished{Nae03, author = "Stefan N{\"a}her", title = "Comparison of Search-Tree Data Structures in {LEDA}", note = "personal communication", } @Article{MehNae90, author = "Kurt Mehlhorn and Stefan N{\"a}her", title = "Bounded Ordered Dictionaries in {$O(\log \log N)$} Time and {$O(n)$} Space", journal = "Information Processing Letters", year = 1990, volume = 35, number = 4, pages = "183--189" } @Article{Emde77, author = "Peter van Emde Boas", title = "Preserving Order in a Forest in Less than Logarithmic Time", journal = "Information Processing Letters", volume = "6", number = "3", pages = "80--82", year = "1977", } @InProceedings{HagSanTra98, author = "T. Hagerup and P. Sanders and J. L. Tr{\"a}ff", title = "An Implementation of the Binary Blocking Flow Algorithm", editor = "K. Mehlhorn", number = "MPI-I-98-1-019, ISSN: 0946-011X", pages = "143--154", series = "Research Reports MPII", booktitle = "2nd Workshop on Algorithm Engineering", year = 1998 } @InProceedings{HagSanTra98www, author = "T. Hagerup and P. Sanders and J. L. Tr{\"a}ff", title = "{\htmladdnormallink{An Implementation of the Binary Blocking Flow Algorithm}{http://www.mpi-sb.mpg.de/{\%7e}wae98/PROCEEDINGS/PAPERS/pap23.ps.gz}}", editor = "K. Mehlhorn", number = "MPI-I-98-1-019, ISSN: 0946-011X", series = "Research Reports MPII", booktitle = "{\htmladdnormallink{2nd Workshop on Algorithm Engineering}{http://www.mpi-sb.mpg.de/{\%7e}wae98/PROCEEDINGS/toc.html}}", year = 1998 } @TechReport{CraEtAl98, author = "A. Crauser and K. Mehlhorn and U. Meyer and P. Sanders", title = "Parallelizing {D}ijkstra's Shortest Path Algorithm", institution = "MPI-Informatik", year = 1998, note = "in preparation" } @InCollection{GraPom00, author = "J. F. Grantham and C. Pomerance", title = "Prime Numbers", booktitle = "Handbook of Discrete and Combinatorial Mathematics", pages = "236--254", publisher = "CRC Press", year = 2000, editor = "K. H. Rosen", chapter = "4.4" } @Book{AWK88, author = "A. V. Aho and B. W. Kernighan and P. J. Weinberger", title = "The {AWK} Programming Language", publisher = "Addison-Wesley", year = 1988 } @Book{WCO00, author = "L. Wall and T. Christiansen and J. Orwant", title = "Programming Perl", publisher = "O'Reilly", year = 2000, edition = "3rd" } @Article{ASTW00, author = "P. Alefragis and P. Sanders and T. Takkula and D. Wedelin", title = "Parallel Integer Optimization for Crew Scheduling", journal = "Annals of Operations Research", year = 2000, volume = 99, number = 1, pages = "141--166", } @InProceedings{AGHSTW98, author = "P. Alefragis and C. Goumopoulos and E. Housos and P. Sanders and T. Takkula and D. Wedelin", title = "Parallel Crew Scheduling in {PAROS}", number = 1470, series = "LNCS", pages = "1104--1113", booktitle = "4th Euro-Par", year = 1998, publisher = "Springer {\copyright}" } @InProceedings{CraEtAl98b, author = "A. Crauser and K. Mehlhorn and U. Meyer and P. Sanders", title = "A Parallelization of {D}ijkstra's Shortest Path Algorithm", series = "LNCS", number = 1450, pages = "722--731", booktitle = "23rd Symposium on Mathematical Foundations of Computer Science", year = 1998, publisher = "Springer", address = "Brno, Czech Republic" } @InProceedings{CraEtAl98bwww, author = "A. Crauser and K. Mehlhorn and U. Meyer and P. Sanders", title = "{\htmladdnormallink{A Parallelization of {D}ijkstra's Shortest Path Algorithm}{wcons_main.ps.gz}}", series = "{\htmladdnormallink{LNCS}{http://www.springer.de/comp/lncs/index.html}}", number = 1450, pages = "722--731", booktitle = "23rd Symposium on Mathematical Foundations of Computer Science", year = 1998, publisher = "Springer {\copyright}", address = "Brno, Czech Republic" } @InProceedings{San99jwww, author = "P. Sanders", title = "{\htmladdnormallink{Parallelizing {NP}-Complete Problems Using Tree Shaped Computations}{http://www.mpi-sb.mpg.de/\%7esanders/papers/jim.ps.gz}}", booktitle = "Journ{\'e}es de l'Informatique Messine (JIM)", year = 1999, address = "Metz", month = "may", note = "invited talk" } @InProceedings{San99j, author = "P. Sanders", title = "Parallelizing {NP}-Complete Problems Using Tree Shaped Computations", booktitle = "Journ{\'e}es de l'Informatique Messine (JIM)", year = 1999, address = "Metz", month = "may", note = "invited talk, {\url{http://www.mpi-sb.mpg.de/~sanders/papers/jim.ps.gz}}" } @Article{MeySan03, author = "U. Meyer and P. Sanders", title = "{$\Delta$}-Stepping: A Parallelizable Shortest Path Algorithm", journal = "Journal of Algorithms", year = 2003, note = "in press" } @Unpublished{MeySan99a, author = "U. Meyer and P. Sanders", title = "{$\Delta$}-Stepping: A Parallelizable Shortest Path Algorithm", note = "{\url{http://www.mpi-sb.mpg.de/~sanders/papers/long-delta.ps.gz}}", year = 1999 } @Unpublished{MeySan99ahab, author = "U. Meyer and P. Sanders", title = "{$\Delta$}-Stepping: A Parallelizable Shortest Path Algorithm", note = "Eingeladen f{\"u}r Journal of Algorithms, {\url{http://www.mpi-sb.mpg.de/~sanders/papers/long-delta.ps.gz}}", } @InProceedings{MeySan98a, author = "U. Meyer and P. Sanders", title = "{$\Delta$}-Stepping: A Parallel Shortest Path Algorithm", series = "LNCS", number = 1461, pages = "393--404", booktitle = "6th European Symposium on Algorithms (ESA)", year = 1998, publisher = "Springer" } @InProceedings{MeySan98awww, author = "U. Meyer and P. Sanders", title = "{\htmladdnormallink{{$\Delta$}-Stepping: A Parallel Shortest Path Algorithm}{wmain.ps.gz}}", series = "{\htmladdnormallink{LNCS}{http://www.springer.de/comp/lncs/index.html}}", number = 1461, pages = "393--404", booktitle = "6th European Symposium on Algorithms (ESA)", year = 1998, publisher = "Springer {\copyright}" } @InProceedings{San98b, author = "P. Sanders", title = "Tree Shaped Computations as a Model for Parallel Applications", booktitle = "ALV'98 Workshop on Application Based Load Balancing", address = "Munich, Germany, 25--26 March", number = "TUM-INFO-02-I9806-100/1.-FI", year = 1998, organization = "SFB 342", series = "TR TU Munich, Germany", note = "{\url{http://www.mpi-sb.mpg.de/~sanders/papers/alv.ps.gz}}" } @InProceedings{San98bs, author = "P. Sanders", title = "Tree Shaped Computations as a Model for Parallel Applications", booktitle = "ALV'98 Workshop on application based load balancing", year = 1998, organization = "SFB 342", publisher = "TU M{\"u}nchen, Germany", note = "{\url{http://www.mpi-sb.mpg.de/~sanders/papers/alv.ps.gz}}" } @InProceedings{San98bwww, author = "P. Sanders", title = "{\htmladdnormallink{Tree Shaped Computations as a Model for Parallel Applications}{alv.ps.gz}}", booktitle = "{\htmladdnormallink{ALV'98 Workshop on application based load balancing}{http://wwwpaul.informatik.tu-muenchen.de/projekte/sfb342/alv/ALV98.html}}", year = 1998, pages = "123--132", organization = "SFB 342", publisher = "TU M{\"u}nchen, Germany", month = "March" } @InProceedings{San99a, author = "P. Sanders", title = "Fast Priority Queues for Cached Memory", series = "LNCS", number = 1619, booktitle = "ALENEX '99, Workshop on Algorithm Engineering and Experimentation ", year = 1999, pages = "312--327", publisher = "Springer" } @InProceedings{San99awww, author = "Peter Sanders", title = "{\htmladdnormallink{Fast Priority Queues for Cached Memory}{falenex.ps.gz}}", series = "{\htmladdnormallink{LNCS}{http://www.springer.de/comp/lncs/index.html}}", booktitle = "ALENEX '99, Workshop on Algorithm Engineering and Experimentation ", year = 1999, note = "{\htmladdnormallink{Extended version in ACM Journal of Experimental Algorithmics}{spqjea.ps.gz}}", number = 1619, pages = "312--327", publisher = "Springer {\copyright}" } @Article{San00b, author = "Peter Sanders", title = "Fast Priority Queues for Cached Memory", journal = "ACM Journal of Experimental Algorithmics", volume = 5, year = 2000, } @Unpublished{San99ahab, author = "P. Sanders", title = "Fast Priority Queues for Cached Memory", note = "Eingeladen f{\"u}r ACM Journal of Experimental Algorithmics, {\url{http://www.mpi-sb.mpg.de/~sanders/papers/falenex.ps.gz}}" } @InProceedings{San99asub, author = "Peter Sanders", title = "{\htmladdnormallink{Fast Priority Queues for Cached Memory}{falenex.ps.gz}}", series = "{\htmladdnormallink{LNCS}{http://www.springer.de/comp/lncs/index.html}}", booktitle = "ALENEX '99, Workshop on Algorithm Engineering and Experimentation ", year = 1999, note = "{\htmladdnormallink{Extended version in ACM Journal of Experimental Algorithmics}{spqjea.ps.gz}}", number = 1619, pages = "312--327", publisher = "Springer {\copyright}" } @InProceedings{San98cpars, author = "P. Sanders", title = "Random Permutations on Distributed, External and Hierarchical Memory", number = 17, series = "PARS-Mitteilungen", pages = "160--165", booktitle = "PARS-Workshop", year = 1998, organization = "GI-ITG: Parallel-Algorithmen, -Rechnerstrukturen und -Systemsoftware", month = "September" } @InProceedings{Tho00, author = "Mikkel Thorup", title = "Even strongly universal hashing is pretty fast.", pages = "496--497", booktitle = "Proceedings of the Eleventh Annual {ACM}-{SIAM} Symposium on Discrete Algorithms", month = jan # "~9--11", publisher = "ACM Press", address = "N.Y.", year = "2000", } @Article{Cle84, author = "J. G. Cleary", title = "Compact Hash Tables Using Bidirectional Linear Probing", journal = "IEEE Transactions on Computers", year = 1984, volume = "C-33", number = 9, pages = "828--834" } @Article{Pearson90, author = "P. K. Pearson.", title = "Fast Hashing of Variable Length Strings.", journal = "Comm. A.C.M.", volume = "33", number = "6", month = jun, year = "1990", keywords = "perfect, hash, hashing, string", abstract = "He discusses use of hash functions of the form: h = 0; n = length(string); for i = 1 through n do h = Table [ h XOR string [i]]; enddo; return h; where Table is a 256-byte array. Each character in the string hashed costs an XOR operation and an indexed read from memory (above the costs of reading the character). This function can {"}sometimes be modified to produce a minimal perfect hashing function over a modest list of words.{"}", } @InProceedings{San99b, author = "P. Sanders", title = "Accessing Multiple Sequences Through Set Associative Caches", series = "LNCS", booktitle = "ICALP", number = 1644, pages = "655--664", year = 1999, } @InProceedings{San99bwww, author = "P. Sanders", title = "\htmladdnormallink{Accessing Multiple Sequences Through Set Associative Caches}{icalp55.ps.gz}", series = "{\htmladdnormallink{LNCS}{http://www.springer.de/comp/lncs/index.html}}", booktitle = "ICALP", number = 1644, pages = "655--664", year = 1999, publisher = "Springer {\copyright}", note = "{\htmladdnormallink{extended version (with K. Mehlhorn)}{icalpfull.ps.gz}}" } @InCollection{BMS02www, series = "{\htmladdnormallink{LNCS}{http://www.springer.de/comp/lncs/index}}", publisher = "Springer {\copyright}", author = "D. Bader and B. Moret and P. Sanders", booktitle = "Experimental Algorithmics From Algorithm Design to Robust and Efficient Software", volume = 2547, pages = "1--23", title = "{\htmladdnormallink{Algorithm Engineering for Parallel Computation}{parallel-algen.ps.gz}}", year = 2002 } @InCollection{BMS02, author = "D. Bader and B. Moret and P. Sanders", booktitle = "Dagstuhl Seminar on Experimental Algorithmics (2000)", title = "Algorithm Engineering for Parallel Computation", booktitle = "Experimental Algorithmics --- From Algorithm Design to Robust and Efficient Software", volume = 2547, pages = "1--23", series = "LNCS", publisher = "Springer", year = 2002 } @Unpublished{BMS02a, author = "D. Bader and B. Moret and P. Sanders", title = "High-Performance Algorithm Engineering for Parallel Computation", note = " ", year = 2002 } @Unpublished{MehSan00a, author = "K. Mehlhorn and P. Sanders", title = "Scanning Multiple Sequences Via Cache Memory", note = "{\url{http://www.mpi-sb.mpg.de/~sanders/papers/icalpfull.ps.gz}}, short version: ICALP '99, pages 655--664" } @Article{San99c, author = "P. Sanders", title = "Analysis of Nearest Neighbor Load Balancing Algorithms for Random Loads", journal = "Parallel Computing", year = 1999, volume = 25, pages = "1013--1033" } @InCollection{San99dwww, author = "P. Sanders", title = "\htmladdnormallink{Berechnungen mit gro{\ss}en {D}atenmengen}{jahrbuch.ps.gz}", booktitle = "Jahrbuch der Max-Planck-Gesellschaft", publisher = "MPG", year = 1999, pages = "534--540", } @InCollection{San99d, author = "P. Sanders", title = "Berechnungen mit gro{\ss}en Datenmengen", booktitle = "Jahrbuch der Max-Planck-Gesellschaft", publisher = "MPG", year = 1999, pages = "534--540", } @InProceedings{San99e, author = "P. Sanders", title = "Asynchronous Random Polling Dynamic Load Balancing", booktitle = "ISAAC: 10th International Symposium on Algorithms and Computation", year = 1999, pages = "37--48", series = "LNCS", number = "1741", address = "Chennai, India, 16--18 December", month = "Dec.", publisher = "Springer-Verlag Berlin", } @InProceedings{San99ewww, author = "P. Sanders", title = "\htmladdnormallink{Asynchronous Random Polling Dynamic Load Balancing}{isaac99.ps.gz}", pages = "37--48", booktitle = "ISAAC: 10th International Symposium on Algorithms and Computation", year = 1999, series = "LNCS", address = "Chennai, India", month = "Dec.", publisher = "Springer {\copyright}", note = "\htmladdnormallink{full paper}{submit.ps.gz}" } @Article{San02b, author = "Peter Sanders", title = "Randomized Receiver Initiated Load Balancing Algorithms for Tree Shaped Computations", journal = "The Computer Journal", year = 2002, pages = "561--573", volume = 45, number = "5", } @InProceedings{FPSS03www, author = "D. Fotakis and R. Pagh and P. Sanders and P. Spirakis", title = "Space Efficient Hash Tables With Worst Case Constant Access Time\htmladdnormallink{full paper}{d-cuckoo.ps.gz}", booktitle = "20th International Symposium on Theoretical Aspects of Computer Science", year = 2003, series = "LNCS", address = "Berlin", publisher = "Springer", pages = "271--282", number = 2607 } @InProceedings{FPSS03, author = "D. Fotakis and R. Pagh and P. Sanders and P. Spirakis", title = "Space Efficient Hash Tables With Worst Case Constant Access Time", booktitle = "20th International Symposium on Theoretical Aspects of Computer Science", year = 2003, series = "LNCS", address = "Berlin", publisher = "Springer", pages = "271--282", number = 2607 } @Article{SanEgnKorboth, author = "P. Sanders and S. Egner and Jan Korst", title = "Fast Concurrent Access to Parallel Disks", journal = "Algorithmica", year = 2003, volume = 35, number = 1, pages = "21--55", note = "short version in 11th SODA, pages 849--858, 2000." } @Article{SanEgnKor03, author = "P. Sanders and S. Egner and Jan Korst", title = "Fast Concurrent Access to Parallel Disks", journal = "Algorithmica", year = 2003, volume = 35, number = 1, pages = "21--55" } @TechReport{SanEgnKor99, author = "P. Sanders and S. Egner and Jan Korst", title = "Fast Concurrent Access to Parallel Disks", institution = "Max-Planck-Institute for Computer Science", year = 1999, number = "MPI-I-1999-1-003", month = "June" } @TechReport{SanEgnKor99www, author = "P. Sanders and S. Egner and Jan Korst", title = "\htmladdnormallink{Fast Concurrent Access to Parallel Disks}{tr-pardisk.ps.gz}", institution = "Max-Planck-Institute for Computer Science", year = 1999, note = "{\htmladdnormallink{updated version}{full-pardisk.ps.gz}}", number = "MPI-I-1999-1-003", month = "June" } @Article{RatSanKni99, author = "U. Rathe and P. Sanders and P. Knight", title = "A Case Study in Scalability: an {ADI} Method for the Two-Dimensional Time-Dependent {D}irac Equation", journal = paco, number = 5, volume = 25, pages = "525--534", month = "may", year = 1999, } @InProceedings{SanTakWed99a, author = "P. Sanders and T. Takkula and D. Wedelin", title = "{\htmladdnormallink{High Performance Integer Optimization for Crew Scheduling}{hpcn.ps.gz}}", booktitle = "7th International Conference on High Performance Computing and Networking Europe", year = 1999, number = 1593, series = "{\htmladdnormallink{LNCS}{http://www.springer.de/comp/lncs/index.html}}", publisher = "Springer {\copyright}", pages = "3--12", note = "{\htmladdnormallink{full paper}{hpcnfull.ps.gz}}" } @InProceedings{DSSS04www, author = "R. Dementiev and P. Sanders and D. Schultes and J. Sibeyn", title = "\htmladdnormallink{Engineering an External Memory Minimum Spanning Tree Algorithm}{emst.ps.gz}", booktitle = "IFIP TCS", year = 2004, address = "Toulouse", } @InProceedings{DSSS04, author = "R. Dementiev and P. Sanders and D. Schultes and J. Sibeyn", title = "{Engineering an External Memory Minimum Spanning Tree Algorithm}", booktitle = "IFIP TCS", year = 2004, address = "Toulouse", pages = {195-208} } @Unpublished{SanTra01, author = "P. Sanders and J. L. Tr{\"a}ff", title = "The Factor Algorithm for All-to-all Communication on Clusters of {SMP} Nodes", note = "Manuscript", year = 2001 } @Unpublished{Sch03, author = "D. Schultes", title = "External Memory Minimum Spanning Trees", note = "Bachelor thesis, Max-Planck-Institut f. Informatik and Saarland University, {\url{???}}", month = "August", year = 2003 } @Unpublished{Tak97, author = "T. Takkula", title = "OPT1/2 1.0, classes dealing with mixed integer problem data", note = "Paros Documentation", year = 1997, annote = "alte Version" } @PhdThesis{Nie96a, author = "R. Niedermeier", title = "Towards Realistic and Simple Models of Parallel Computation", school = "University of T{\"u}bingen", year = 1996, type = "Dissertation" } @Unpublished{Lux98, author = "Luxburg, Ulrike von", title = "Lokalit{\"atsma\ss}e von Peanokurven", note = "Studienarbeit Uni T{\"u}bingen, Betreuer K. Reinhard", year = 1998 } @Unpublished{Nie96, author = "R. Niedermeier", title = "Exact Determination of the Manhattan Distance for Hilbert Indexings of Grids", year = 1995 } @Article{Pan03, author = "A. Panholzer", title = "Analysis of Multiple Quickselect Variants", journal = "Theoretical Computer Science", year = 2003, volume = 302, pages = "45--91" } @Article{MG91, author = "J. Misra and D. Gries", title = "A Constructive Proof of Vizing's Theorem", journal = "Inf. Process. Lett.", year = 1991, volume = 41, number = 3, pages = "131--133" } Jayadev Misra, David Gries: A Constructive Proof of Vizing's Theorem. Inf. Process. Lett. 41(3): 131-133 (1992). 1991. @Misc{Par96, author = "Parcella 96", title = "List of Participants", year = 1996 } @InProceedings{CheRot94, author = "L. T. Chen and D. Rotem", title = "Optimal response time retrieval of replicated data (extended abstract)", booktitle = "13th {ACM} Symposium on Principles of Database Systems", volume = "13", publisher = "ACM Press", ISBN = "0-89791-642-5", pages = "36--44", year = "1994", bibdate = "Wed Oct 25 12:40:13 MDT 2000", url = "http://www.acm.org/pubs/articles/proceedings/pods/182591/p36-chen/p36-chen.pdf; http://www.acm.org/pubs/citations/proceedings/pods/182591/p36-chen/; http://www.acm.org:80/pubs/citations/proceedings/pods/182591/p36-chen/", abstract = "This work deals with the problem of finding efficient access plans for retrieving a set of pages from a multi-disk system with replicated data. This paper contains two results related to this problem: (a) We solve the problem of finding an optimal access path by transforming it into a network flow problem. We also indicate how our method may be employed in dynamic environments where some (or all) of the disks have a preexisting load, are heterogeneous, and reside on different servers. (b) We present a lower bound for the worst case response time of a request under all replication schemes, and also discuss the replication scheme that results in this lower bound. We then use simulation to show how this replication scheme can also greatly reduce the average case response time.", acknowledgement = ack-nhfb, generalterms = "Algorithms; Design; Performance; Theory; Verification", keywords = "ACM; algorithms; computability; database systems; design; performance; SIGACT; SIGART; SIGMOD; theory; verification", subject = "{\bf G.2.2} Mathematics of Computing, DISCRETE MATHEMATICS, Graph Theory, Network problems. {\bf H.2.2} Information Systems, DATABASE MANAGEMENT, Physical Design, Access methods. {\bf F.2.2} Theory of Computation, ANALYSIS OF ALGORITHMS AND PROBLEM COMPLEXITY, Nonnumerical Algorithms and Problems, Computations on discrete structures.", } @Article{EdeRotWel89, author = "H. Edelsbrunner and G. Rote and E. Welzl", title = "Testing the Necklace Condition for Shortest tours and Optimal Factors in the Plane", journal = "Theoretical Computer Science", year = 1989, volume = 66, pages = "157--180" } @Unpublished{Wel01, author = "E. Welzl", title = "Combinatorial Methods for Linear Programming and Related Problems", note = "course notes, ADFOCS 01", year = 2001, annote = "LP type problem" } @Article{AsaEtAl97, title = "Space-filling curves and their use in the design of geometric data structures", author = "Tetsuo Asano and Desh Ranjan and Thomas Roos and Emo Welzl and Peter Widmayer", pages = "3--15", journal = "Theoretical Computer Science", year = "1997", volume = "181", number = "1", } @InProceedings{AsaEtAl95, author = "T. Asano and D. Ranjan and T. Roos and E. Welzl and P. Widmayer", title = "Space Filling Curves and Their Use in the Design of Geometric Data Structures", booktitle = "{LATIN} '95: theoretical informatics: second Latin American Symposium", number = 911, series = "LNCS", year = 1995, address = "Valparaiso, Chile", month = "April", pages = "36ff" } @Article{AsaEtAl95, author = "T. Asano and D. Ranjan and T. Roos and E. Welzl and P. Widmayer", title = "Space Filling Curves and Their Use in the Design of Geometric Data Structures", journal = "??", year = 1995, annote = "'verdrehte' Hilbertkurve ermoeglichen es mit max. 3 Zugriffen asympt. optimaler Groesse auf eine Datei ein quadratisches Teilgebiet zu lesen." } @Article{ GotLin96, author = {C. Gotsman and M. Lindenbaum}, title = {On the Metric Properties of Discrete Space-Filling Curves}, journal = {IEEE Transactions on Image Processing}, volume = {5}, number = {5}, pages = {794--797}, month = {May}, year = {1996} } @Article{BhaCai93, author = "S. Bhatt and Jin-Yi Cai", title = "Taking Random Walks to Grow Trees in Hypercubes", journal = jacm, year = 1993, volume = 40, number = 3, pages = "741--764", annote = "Ergebnis schlechter als Leighton und Co. Warum zitieren sie ihn? Verdacht: Nur preprint gelesen." } @InProceedings{SevAluFut00, author = "F. E. Sevilgen and S. Aluru and N. Futamura", title = "A Provably Optimal, Distribution-Independent Parallel Fast Multipole Method", booktitle = "Proc. IPDPS", pages = "77--84", year = 2000, annote = "schoenes Papier. Relativ theoretisch. Gutes Beispiel fuer mein Lieblingsparallelmodell mit kollektiven Operationen als Basis. Verfahren ohne Lastverteilung. Offene Frage: kann man auf Maschinen mit sublinearer Bisektionsbreite mit LV Beweisbar besser sein?" } @InProceedings{LiuBha94, author = "P. Liu and S. N. Bhatt", title = "Experiences with Parallel N-body Simulation", pages = "122--131", booktitle = spaa, year = 1994, address = "Cape May, New Jersey", annote = "Referenz auf Verwendung variabler Zeitschritte, Barnes Hut wird als Konkurrenzfaehig gegen Multipole dargestellt. (Quadrupolmomente werden allerdings benutzt.), Singh wird kleingemacht, Referenz auf library fuer n-body abstraktionen. Wenig Cach aendereungen im seq, Teil werden nachgewiesen." } %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Allgemeines @Unpublished{Ach94, author = "Alf-Christian Achilles", title = "Eine L{\"o}sung auf der Suche nach Problemen", year = 1994 } @InProceedings{Ach95a, author = "Alf-Christian Achilles", title = "Optimal Emulation of Meshes on Meshes-of-Trees", booktitle = "{EURO-PAR} International Conference on Parallel Processing", year = 1995, pages = "193--204" } @PhdThesis{Ach95b, author = "Alf-Christian Achilles", title = "Effiziente Emulation von Verbindungsnetzwerken", school = uka, year = 1995, type = "Dissertation" } @Misc{Ach95c, author = "Alf-Christian Achilles", title = "A Collection of Computer Science Bibliographies", howpublished = "{\tt http://liinwww/bibliography/index.html}", year = 1995 } @Article{AfeEtAl96, author = "Y. Afek and B. Awerbuch and S. Plotkin and M. Saks", title = "Local Management of a Global Recource in Communication Network", journal = jacm, year = 1996, volume = 43, number = 1, pages = "1--19", annote = "verteilter Algorithmus der hoechstens M Einheiten einer globalen Ressource zuteilt aber hoechstens dann eine Zuteilung ablehnt, wenn weniger als M-W zugeteilt worden sein werden :-). Legen besonderen Werte auf geringe nachrichtenkomplexitaet" } @Book{Akl89, author = "S. G. Akl", title = "The Design and Analysis of Parallel Algorithms", publisher = "Prentice-Hall", year = 1989 } @Book{BroSem79, author = "I. N. Bronstein and K. A. Semendjajew", title = "Taschenbuch der Mathematik", publisher = "Teubner", year = 1979 } @Article{Bro88, author = "R. Brown", title = "Calendar Queues: A Fast {$O(1)$} Priority Queue Implementation for the Simulation Event Set Problem", journal = cacm, year = 1988, volume = 31, number = 10, pages = "1220--1227", annote = "Leistung nur empirisch fuer bestimmte Verteilungen gemessen. Einordnung in Buckets." } @InProceedings{EriLadLaM94, author = "K. B. Erickson and R. E. Ladner and A. LaMarca", title = "Optimizing Static Calendar Queues", pages = "732--743", ISBN = "0-8186-6580-7", editor = "Shafi Goldwasser", booktitle = "Proceedings of the 35th Annual Symposium on Foundations of Computer Science", month = nov, publisher = "IEEE Computer Society Press", address = "Los Alamitos, CA, USA", year = "1994", } @Article{FisPat94, author = "M. J. Fischer and M. S. Paterson", title = "Fishspear: A Priority Queue Algorithm", journal = jacm, year = 1994, volume = 41, number = 1, pages = "3--30" } @Article{JuuWij98, author = "B. Juurlink and H. A.G. Wijshoff", title = "A Quantitative Comparison of Parallel Computation Models", journal = "ACM Transactions on Computer Systems", year = 1998, volume = 16, number = 3, pages = "271--318" } @InProceedings{CulEtAl93, author = "D. Culler and R. Karp and D. Patterson and A. Sahay and K. E. Schauser and E. Santos and R. Subramonian and T. v. Eicken", title = "{LogP}: Towards a Realistic Model of Parallel Computation", booktitle = "Fourth {ACM} {SIGPLAN} Symposium on Principles and Practice of Parallel Programming", year = 1993, pages = "1--12", address = "San Diego, CA, 19--22 May", publisher = "ACM, New York", annote = "Lokale Kommunikation wird nicht belohnt. Lange Nachrichten passen irgendwie nicht ins Bild." } @Article{AISS97, author = "Albert Alexandrov and Mihai F. Ionescu and Klaus E. Schauser and Chris Scheiman", title = "{LogGP}: Incorporating Long Messages into the {LogP} Model for Parallel Computation", journal = "Journal of Parallel and Distributed Computing", volume = "44", number = "1", pages = "71--79", day = "10", month = jul, year = "1997", coden = "JPDCER", ISSN = "0743-7315", bibdate = "Tue Mar 17 17:08:12 MST 1998", acknowledgement = ack-nhfb, } @Book{Tuf83, author = "Edward R. Tufte", title = "The Visual Display of Quantitative Information", publisher = "Graphics Press", address = "Cheshire, Connecticut, U.S.A.", year = "1983", ISBN = "0-9613921-0-X", } @InProceedings{AISS95, author = "Albert Alexandrov and Mihai Ionescu and Klaus E. Schauser and Chris Scheiman", title = "{LogGP} : Incorporating Long Messages into the Log{P} model : One step closer towards a realistic model for parallel computation", pages = "95--105", booktitle = "7th Annual Symposium on Parallel Algorithms and Architectures ({SPAA} '95)", ISBN = "0-89791-717-0", month = jul, publisher = "ACM", address = "New York, USA", year = "1995", } @InProceedings{CulEtAl93s, author = "D. Culler and others", title = "{LogP}: Towards a Realistic Model of Parallel Computation", booktitle = "Fourth {ACM} {SIGPLAN} Symposium on Principles and Practice of Parallel Programming", year = 1993, pages = "1--12", address = "San Diego", annote = "Lokale Kommunikation wird nicht belohnt. Lange Nachrichten passen irgendwie nicht ins Bild." } @Article{CulEtAl96, author = "D. Culler and R. Karp and D. Patterson and A. Sahay and K. E. Schauser and E. Santos and R. Subromonian and T. v. Eicken", title = "{LogP} a Practical Model of Parallel Computation", journal = cacm, year = 1996, volume = 39, number = 11, pages = "78--85" } @Article{DinSud94, author = "A. Dingle and I. H. Sudborough", title = "Efficient Mappings of Pyramid Networks", journal = tpds, year = 1994, volume = 5, number = 10, pages = "1009--1017", annote = "Benutzen Hilbertkurven -> Miller/Stout" } @Article{GilMat94, author = "J. Gil and Y. Matias", title = "Designing Algorithms by Expectations", journal = ipl, year = 1994, volume = 51, pages = "31--34", annote = "Anwendung von Chernoff Schranken auf abhangige Folgen. Schluss von der Erfolgswahrscheinlichkeit einer Iteration auf dern Erwartungswert der Ausfuhrungszeit." } @Article{Mot94, title = "Average-Case Analysis of Algorithms for Matchings and Related Problems", author = "Rajeev Motwani", area = "Operations Research", pages = "1329--1356", journal = "Journal of the ACM", month = nov, year = "1994", volume = "41", number = "6", references = "\cite{STOC::BollobasFF1985} \cite{STOC::Broder1986} \cite{FOCS::EvenK1975} \cite{STOC::FederM1991} \cite{STOC::GabowT1988} \cite{STOC::JerrumS1988} \cite{FOCS::KarpS1981} \cite{FOCS::MicaliV1980}", } @Article{Han95, author = "Y. Han", title = "An Improvement on Parallel Computation of a Maximal Matching", journal = "Information Processing Letters", year = 1995, volume = 56, number = 6, pages = "343--348" } @Article{HopKar73, author = "J. E. Hopcroft and R. M. Karp", title = "An {O}(n**5/2) algorithm for maximum matchings in bipartite graphs", journal = "SIAM Journal on Computing", volume = "2", pages = "225--231", year = "1973", } @Book{HopUll79, author = "J. E. Hopcroft and J. D. Ullman", title = "Introduction to Automata Theory, Languages, and Computation", publisher = "Addison-Wesley", year = 1979, annote = "Blums speedup theorem" } @InProceedings{GNL01, author = "D. J. Gonzalez and J. J. Navarro and J. Larriba-Pey", title = "Fast Parallel In-Memory 64-bit Sorting", booktitle = "ACM Supercomputing", pages = "114--122", year = 2001, annote = "nett aber nichts algorithmisch neues" } @InProceedings{MatVis90, title = "On Parallel Hashing and Integer Sorting (Extended Summary)", author = "Y. Matias and U. Vishkin", booktitle = "17th ICALP", year = "1990", series = "LNCS", number = "443", pages = "729--743", } @InProceedings{MatVis91, author = "Y. Matias and U. Vishkin", title = "Converting High Probability into Nearly-Constant Time -- with Applications to Parallel Hashing", pages = "307--316", booktitle = stoc, year = 1991 } @InProceedings{GodMatVis94, author = "M. T. Goodrich and Y. Matias and U. Vishkin", booktitle = "5th ACM-SIAM Symp. on Discrete Algorithms (SODA),", title = "Optimal Parallel Approximation Algorithms for Prefix Sums and Integer Sorting", year = "1994", url = "http://www.cs.jhu.edu/{\%7e}goodrich/pubs/prefix.ps", pages = "241--250", scope = "scan", } @Article{Rab89, author = "M. O. Rabin", title = "Efficient Dispersal of Information for Security, Load Balancing and Fault Tolerance", journal = "Journal of the ACM", year = 1989, volume = 36, number = 2, pages = "335--348", annote = "One of the oldest references for r out of R schemes? No concurrent disk access however. (Routing and fault tolerance. Detailed discussion of the coding schemes" } @Article{CPRV98, author = "I. D. D. Curcio and A. Puliafito and S. Riccobene and L. Vita", title = "Design and evaluation of a multimedia storage server for mixed traffic", journal = "Multimedia Systems", year = 1998, volume = 6, pages = "367--381", annote = "Nothing really new as far as I can see. But perhaps its interestin to compare the messages with what Phillips of Uni-SB does." } @Unpublished{ABL01, author = "D. Arnon and E. Bachmat and T. K. Kam", title = "On the Macroscopic Approach to Storage System Optimization", note = "??", year = "2001?" } @Unpublished{AlonBachmat04, author = "Noga Alon and Eitan Bachmat", title = "Regular Graphs Whose Subgraphs Tend to be Acyclic", note = "nimm regulaeren Zufallsgraph und schmeisse kleine Kreise aktiv raus", year = 2004 } @TechReport{KorCou98, author = "J. Korst and P. Coumans", title = "Asynchronous Control of Disks in Video Servers", institution = "Philips Research Laboratories", year = 1998, number = "NL-MS-19.649", address = "Eindhoven, the Netherlands" } @InProceedings{Korst97, author = "J. Korst", title = "Random Duplicate Assignment: An Alternative to Striping in Video Servers", pages = "219--226", booktitle = "ACM Multimedia", year = 1997, address = "Seattle" } @Book{Tri82, author = "K. S. Trivedi", title = "Probability and Statistics with Reliability, Queueing and Computer Science Applications", publisher = "Prentice Hall", address = "Englewood Cliffs", year = 1982, ISBN = "0-13-711564-4", descriptor = "Markovkette, Statistik, Stochastischer Prozess, Wahrscheinlichkeitstheorie, Wartenetz, Warteschlangennetz, Warteschlangentheorie, Zuverlaessigkeitstheorie, Queue, Queueing", annote = "Jop hat es. War Grundlage fuer Ausrechnung der erwarteten queue length bei zufaelligem Schreiben. Besprechungen des Buches sind erschienen in: 1. Angewandte Informatik 3/83, S. 131 2. ACM Sigmetrics, Vol. 11, Nr. 3, S. 14, 1982", } @Book{Nelxx, author = "R. Nelson", title = "Probability, Stochastic Processe and Queueing Theory", publisher = "Springer", year = "19??", annote = "Abschnitt ueber qeuing theorie kopiert" } @InProceedings{NRMPTW97, author = "G. Nerjes and Y. Romboyannakis and P. Muth and M. Paterakis and P. Triantafillou and G. Weikum", title = "On Mixed-Workload Multimedia Storage Servers with Guaranteed Performance and Service Quality", booktitle = "3rd Workshop on Multimedia Information Systems", year = 1997, pages = "63--72", address = "Como, Italy" } @Article{NMPRTW99, author = "Nerjes, G. and Muth, P. and Paterakis, M. and Romboyannakis, Y. and Triantafillou, P. and Weikum, G.", title = "Incremental Scheduling of Mixed Workloads in Multimedia Information Servers", journal = "Journal of Multimedia Tools and Applications", year = 2000, volume = 11, number = 1, pages = "249--273", } Nerjes, G., Muth, P., Paterakis, M., Romboyannakis, Y., Triantafillou, P., Weikum, G.: Incremental Scheduling of Mixed Workloads in Multimedia Information Servers to appear in: Special Issue of the Journal of Multimedia Tools and Applications, Kluewer 1999 @InProceedings{NerMutWei97, author = "G. Nerjes and P. Muth and G. Weikum", title = "Stochastic Service Guarantees for Continuous Data on Multi-Zone Disks ", booktitle = "16th Symposium on Principles of Database Systems", year = 1997 } @Article{SalTso99, author = "B. Salzberg and V. J. Tsotras", title = "Comparison of Access Methods for Time-Evolving Data", journal = "ACM Computing Surveys", year = 1999, volume = 31, number = 2, pages = "158--221" } @InProceedings{JCJ03, author = "S. Jaggi and P. S. Chou and K. Jain", title = "Low Complexity Algebraic Multicast Network Codes", booktitle = "International Symposium on Information Theory", year = 2003, month = "July", organization = "IEEE", note = "1 page abstract, to appear" } @InProceedings{JMS03, author = "K. Jain and M. Mahdian and M. R. Salavatipour", title = "Packing {S}teiner Trees", booktitle = "14th ACM-SIAM Symposium on Discrete Algorithms", year = 2003, } @Unpublished{BalSri03, title = "Approximate Implementation of Minimum Multicast Congestion --- Implementation versus Theory", author = "A. Baltz and A. Srivastav", note = "Manuscript" } @InProceedings{JanZha02, author = "K. Jansen and H. Zhang", title = "An approximation algorithm for the multicast congestion problem via minimum {S}teiner trees", booktitle = "3rd International Workshop on Approximation and Randomized Algorithms in Communication Networks (ARANCE)", year = 2002, address = "Rome, Italy" } @InProceedings{CarVem00, author = "B. Carr and S. Vempala", title = "Randomized meta-rounding", booktitle = "32nd ACM Symposium on the Theory of Computing", pages = "58--62", year = 2000, note = "also in Random Structures and Algorithms, 20(3):343--352, 2002" } 13.Randomized meta-rounding. (Bob Carr) Proc. of the 32nd ACM Symposium on the Theory of Computing (STOC '00), Portland, 2000. @InProceedings{VemVoe99, author = "S. Vempala and B. V{\"o}cking", title = "Approximating Multicast Congestion", booktitle = "10th Int. Symp. on Algorithms and Computation", pages = "367--372", year = 1999, number = 1741, series = "LNCS", address = "Chennai", publisher = "Springer" } S. Vempala and B. V�king. Approximating Multicast Congestion. In Proc. 10th ISAAC (Chennai, India, 1999). Abstract or compressed postscript . @InProceedings{Voe99, author = "B. V{\"o}cking", title = "How Asymmetry Helps Load Balancing", booktitle = "40th Symposium on Foundations of Computer Science", organization = "IEEE", pages = "131--140", year = 1999 } @InProceedings{RaaSte98, author = "M. Raab and A. Steger", title = "``Balls into Bins'' -- {A} Simple and Tight Analysis", booktitle = "RANDOM: International Workshop on Randomization and Approximation Techniques in Computer Science", volume = "1518", pages = "159--170", publisher = "LNCS", year = "1998", } @Article{BHH96, author = "B. Bhattacharya and P. Hell and J. Huang", title = "A Linear Algorithm for Maximum Weight Cliques in Proper Circular Arc Graphs", journal = "SIAM Journal on Discrete Mathematics", volume = "9", number = "2", pages = "274--289", month = may, year = "1996", ISSN = "0895-4801 (print), 1095-7146 (electronic)", keywords = "adjacency lists; algorithm complexity; computational complexity; graph theory; inclusion-free family; linear-time algorithm; maximum weight cliques; optimisation; proper circular arc graphs; $q$-coloring; sorted simple family; weighted graph", } @InProceedings{BCSV00, author = "P. Berenbrink and A. Czumaj and A. Steger and B. V{\"o}cking", title = "Balanced Allocations: The Heavily Loaded Case", pages = "745--754", booktitle = "32th Annual {ACM} Symposium on Theory of Computing", year = 2000, } @Article{CzuSte01, author = "A. Czumaj and V. Stemann", title = "Randomized Allocation Processes", journal = "Random Structures {\&} Algorithms", year = 2001, volume = 18, number = 4, pages = "297--331" } @InProceedings{CzuSte97, author = "A. Czumaj and V. Stemann", title = "Randomized Allocation Processes", pages = "194--203", booktitle = "38th Symposium on Foundations of Computer Science (FOCS)", year = 1997, organization = "IEEE" } @Article{PitSpeWor96, author = "B. Pittel and J. Spencer and N. Wormald", title = "Sudden Emergence of a giant $k$-core in random graph", journal = "J. Combinatorial Theory, Series B", year = 1996, volume = 67, pages = "111-151" } @Unpublished{CSW03, author = "J. Cain and P. Sanders and N. Wormald", title = "A Random Multigraph Process for Linear Time {RDA} Disk Scheduling", note = "manuscript in preparation", year = 2003 } @InProceedings{JurKut01, author = "T. Jurdzinski and M. Kutylowski", title = "Communication Gap for Finite Memory Devices", booktitle = "ICALP", year = 2001 } @InProceedings{DGP02, author = "J. Dumas and T. Gautier and C. Pernet", title = "Finite Field Linear Algebra Subroutines", booktitle = "ISSAC", pages = "63--74", year = 2002, address = "Lille", organization = "ACM" } @Article{Ima80, author = "K. Imamura", title = "A method for computing addition tables in {$GF(p^n)$}", journal = "IEEE Transactions on Information Theory", year = 1980, volume = 26, pages = "367--369" } @InProceedings{CzuEtAl96, author = "A. Czumaj and P. Knarek and M. Kutylowski and K. Lorys", title = "Fast Generation of Random Permutations via Network Simulation", pages = "246--260", series = "LNCS", number = "1136", booktitle = "4th European Symposium on Algorithms", year = 1996 } @InProceedings{ColGru02, author = "D. Colarelli and D. Grunwald", title = "Massive Arrays of Idle Disks For Storage Archives", booktitle = "SC'2002 Conference CD", publisher = "IEEE/ACM SIGARCH", address = "Baltimore, MD", month = nov, year = "2002", keywords = "system components,", abstract = "The declining costs of commodity disk drives is rapidly changing the economics of deploying large amounts of online or near-line storage. Conventional mass storage systems use either high performance RAID clusters, automated tape libraries or a combination of tape and disk. In this paper, we analyze and alternative design using massive arrays of idle disks, or MAID. We argue that this storage organization provides storage densities matching or exceeding those of tape libraries with performance similar to disk arrays. Moreover, we show that with effective power management of individual drives, this performance can be achieved using a very small power budget. In particular, we show that our power management strategy can result in performance comparable to an always-on RAID system while using 1/15th the power of such a RAID system.\par http://www.sc-conference.org/sc2002/", } @InProceedings{MadGibFal99, author = "R. M. Madhyastha and G. A. Gibson and C. Faloutsos", title = "Informed Prefetching of Collective Input/Output Requests", booktitle = "ACM Supercomputing", year = 1999, annote = "two phase I/O, batched I/O, brauchen lookahead D^2" } @InProceedings{BleEtAl95, author = "G. E. Blellock and P. B. Gibbons and Y. Matias", title = "Provably Efficient Scheduling for Languages with Fine-Grained Parallelism", booktitle = spaa, year = 1995, pages = "1--12", annote = "Nur deterministische Abhaengigkeiten, PRAM. Tpar in O(Tseq/n + Tcritical log n" } @InProceedings{GibEtAl94, author = {P. B. Gibbons and Y. Matias and V. Ramachandran}, title = {Efficient Low Contention Parallel Algorithms}, booktitle = spaa, year = 1994, address = {Cape May, NJ}, pages = {236--247} } InProceedings{Vis92, author = "U. Vishkin", title = "A Case for the {PRAM} as a Standard Programmer's Model", series = "LNCS", number = "678", booktitle = "Heinz Nixdorf Symposium on Parallel Architectures and Their Efficient Use", year = "1992", } @InProceedings{GilEtAl91, author = "J. Gil and Y. Matias and U. Vishkin", title = "Towards a Theory of Nearly Constant Time Parallel Algorithms", pages = "698--710", booktitle = focs, year = 1991, publisher = "IEEE", annote = "Total abgedrehter Kram. Extrem kompakt. Martingale Tail inequality oder Azumas Theorem wird erwahnt???" } @Article{Gil58, author = "B. N. Gilbert", title = "Gray Codes and Paths on the $n$-Cube", journal = "Bell System Technical Journal", year = 1958, month = "May", pages = "815--826", annote = "Wie erhalte ich alle moeglichen Hamiltonpfade durch einen Hyperwuerfel?" } @Article{Gil84, author = "W. J. Gilbert", title = "A Cube filling Hilbert Curve", journal = "The Mathematical Intelligencer", year = 1984, volume = 6, number = 3, pages = 78, annote = "Beziehung Gray-Codes <-> Hilbertkurven" } @Article{KruBab96, author = "P. Krueger and D. Babbar", title = "The Effects of Precedence and Priority Constraints on the Performance of Scan Scheduling for Hypercube Multiprocessors", journal = jpdc, year = 1996, volume = 39, pages = "95--104" } @Manual{Intel97, title = "Intel Archtecture Software Developer's Manual. Volume I: Basic Architecture", organization = "Intel Corporation", address = "P.O. Box 5937, Denver, CO, 80217-9808, \url{http://www.intel.com}", note = "Ordering Number 243190", year = 1997 } @article{Den80, author = {P.J. Denning}, title = {What is experimental computer science?}, journal = {Comm.~ACM}, volume = {23}, number = {10}, year = {1980}, pages = {543--544} } @inproceedings{FiMe97, author = {U. Finkler and K. Mehlhorn}, title = {Runtime prediction of real programs on real machines}, booktitle = {SODA'97}, year = {1997}, pages = {380--389} } @InProceedings{Sch99, author = "Uwe Sch{\"{o}}ning", title = "A Probabilistic Algorithm for $k$-SAT and Constraint Satisfaction Problems", booktitle = "40th IEEE Symposium on Foundations of Computer Science", pages = "410--414", year = 1999 } @InProceedings{MehSch00, author = "K. Mehlhorn and G. Sch{\"a}fer", title = "Implementation of $O(nm \log n)$ weighted matchings: The power of data structures", booktitle = "Workshop on Algorithm Engineering", year = 2000, series = "LNCS", publisher = "Springer", note = "to appear" } @book{FeLeSa77, author = {R.P. Feynman and R.B. Leighton and M. Sands}, title = {The Feynman Lectures on Physics}, publisher = {Addison-Wesley}, edition = {6}, year = {1977} } @article{Den81, author = {P.J. Denning}, title = {Performance analysis : {E}xperimental computer science at its best}, journal = {Comm.~ACM}, volume = {24}, number = {11}, year = {1981}, pages = {725--727} } @Book{Aus01, author = "M. H. Austern", title = "Generic programming and the STL : using and extending the C++ standard template library", publisher = "Addison-Wesley", year = 2001, edition = 7 } Austern, Matthew H.: Generic programming and the STL : using and extending the C++ standard template library. Addison-Wesley professional computing series. 7. print. edition. Addison-Wesley (2001). @Manual{SGI97, title = "Multiprocessing C/C++ Compiler Directives", organization = "SGI", year = 1997, } @Manual{SGI97, title = "Origin2000 Architecture", organization = "SGI", year = 1997, } @Manual{SGI97a, title = "Running Programs under MPI", organization = "SGI", year = 1997, note = "Chapter 11, some Handbook for Origin2000" } @Manual{MIPS96, title = "R10000 Microprocessor User's Manual", organization = "MIPS Technologies, Inc.", edition = "2.0", year = 1998, note = "\url{http://www.mips.com}" } @InProceedings{Kel96, author = "J. Keller", title = "The 21264: A Superscalar Alpha Processor with Out-of-Order Execution", booktitle = "Microprocessor Forum", year = 1996, month = "October" } @Article{BowEtAl95, author = "William J. Bowhill and Shane L. Bell and Bradley J. Benschneider and Andrew J. Black and Sharon M. Britton and Ruben W. Castelino and Dale R. Donchin and John H. Edmondson and Harry R. {Fair, III} and Paul E. Gronowski and Anil K. Jain and Patricia L. Kroesen and Marc E. Lamere and Bruce J. Loughlin and Shekhar Mehta and Robert O. Mueller and Ronald P. Preston and Sribalan Santhanam and Timothy A. Shedd and Michael J. Smith and Stephen C. Thierauf", title = "Circuit Implementation of a {300-MHz} 64-bit Second-generation {CMOS Alpha CPU}", journal = "Digital Technical Journal of Digital Equipment Corporation", volume = "7", number = "1", pages = "100--118", month = "Winter", year = "1995", coden = "DTJOEL", ISSN = "0898-901X", bibdate = "Thu Mar 20 18:15:43 MST 1997", url = "ftp://ftp.digital.com/pub/Digital/info/DTJ/v7n1/Circuit_Implementation_of_a_30_01jul1995DTJH08P8.ps; http://www.digital.com:80/info/DTJH08/DTJH08SC.TXT", abstract = "A 300-MHz, custom 64-bit VLSI, second generation Alpha CPU chip has been developed. The chip was designed in a 0.5-$\mu$m CMOS technology using four levels of metal. The die size is 16.5 mm by 18.1 mm, contains 9.3 million transistors, operates at 3.3 V, and supports 3.3-V\slash 5.0-V interfaces. Power dissipation is 50W. It contains an 8-KB instruction cache; an 8-KB data cache; and a 96-KB unified second-level cache. The chip can issue four instructions per cycle and delivers 1,200 mips/600 MFLOPS (peak). Several noteworthy circuit and implementation techniques were used to attain the target operating frequency. This paper focuses on the circuit implementation of the Alpha 21164 CPU. Some of the significant circuit design challenges encountered during the project are discussed. The paper begins with an introductory overview of the chip microarchitecture. It continues with a description of the floorplan and the physical layout of the chip. The next section discusses the clock distribution and latch design. This is followed by an overview of the circuit design strategy and some specific circuit design examples. The paper concludes with information about design (physical and electrical) verification and CAD tools.", acknowledgement = ack-nhfb, classcodes = "B1265F (Microprocessors and microcomputers); B1130 (General circuit analysis and synthesis methods); C5130 (Microprocessor chips); C7410D (Electronic engineering computing)", classification = "B1130 (General circuit analysis and synthesis methods); B1265F (Microprocessors and microcomputers); C5130 (Microprocessor chips); C7410D (Electronic engineering computing)", keywords = "1200 MIPS; 300 MHz; 600; 600 MFLOPS; 64 Bit; 64 bit; Alpha 21164 CPU; Chip microarchitecture; chip microarchitecture; circuit design; Circuit design; Clock distribution; clock distribution; CMOS Alpha CPU; Floorplan; floorplan; integrated circuit layout; Latch design; latch design; layout; MFLOPS; microprocessor chips; physical; Physical layout; second-generation; Second-generation; VLSI", numericalindex = "Frequency 3.0E+08 Hz; Computer speed 6.0E+08 FLOPS; Computer execution rate 1.2E+09 IPS; Word length 6.4E+01 bit", thesaurus = "Integrated circuit layout; Microprocessor chips", treatment = "P Practical; R Product Review", } @Article{MitDur86, author = "G. Mitchison and R. Durbin", title = "Optimal Numberings of an $N\times N$ Array", journal = "SIAM J. Alg. Disc. Meth.", year = 1986, volume = 7, number = 4, pages = "571--582", annote = "computational geometry Standpunkt. unklar " } @Article{Gol82, author = "L. M. Goldschlager", title = "A universal interconnection pattern for parallel computers", journal = jacm, year = 1982, volume = 29, number = 4, pages = "1073--1086", annote = "Def. von feasible architecture als constant degree network" } @Article{Hil91, author = "D. Hilbert", title = "{\"U}ber die stetige {A}bbildung einer {L}inie auf ein {F}l{\"a}chenst{\"u}ck", journal = "Mathematische Annalen", year = 1891, volume = 38, pages = "459--460" } @Article{Pea90, author = {G. Peano}, title = {Sur une courbe qui remplit toute une aire plane}, journal = {Mathematische Annalen}, volume = {36}, pages = {157--160}, year = {1890} } @Article{Gon98, author = "T. F. Gonzales", title = "Complexity and Approximations for Multimessage Multicasting", journal = jpdc, year = 1998, volume = 55, pages = "215--235", annote = "irregular gossiping, nur interessant wenn die Hardware vervielfaeltigen kann" } @Article{GonEtAl95, author = "A. Gonz{\'a}les", title = "Executing Algorithms with Hypercube Topology on Torus Multicomputers", journal = tpds, year = 1995, volume = 6, number = 8, pages = "803--814", annote = "Referenz auf nichttiviale Einbettung mit kleiner max. Dilation" } @Book{Hwa93, author = "K. Hwang", title = "Advanced Computer Architecture -- Parallelism Scalability Programmability", publisher = "McGraw Hill", year = 1993, annote = "Ausfuer" } @InProceedings{Lei85, author = "C. E. Leiserson", title = "Fat trees: Universal networks for hardware efficient supercomputing", pages = "393--402", booktitle = icpp, year = 1985 } @InProceedings{AAFL96, author = "Baruch Awerbuch and Yossi Azar and Amos Fiat and Tom Leighton", title = "Making Commitments in the Face of Uncertainty: How to Pick a Winner Almost Every Time", pages = "519--530", booktitle = "Proceedings of The Twenty-Eighth Annual {ACM} Symposium On The Theory Of Computing ({STOC} '96)", ISBN = "0-89791-785-5", month = may, publisher = "ACM Press", address = "New York, USA", year = "1996", annote = "application: scheduling background jobs on a NOW. When little is known about future speed or availability. video on demand scheduling, on-line set covering. random assignment weighted using past behavior is better than oblivious assigment" } @InProceedings{ChoEtAl94, author = "F. T. Chong and E. A. Brewer and F. T. Leighton and Knight Jr., T. F.", title = "Building a better butterfly: The multiplexed metabutterfly", booktitle = "International Symposium on Parallel Architectures Algorithms and Networks", year = 1994, address = "Kanazawa, Japan, 14--16 December", annote = "ueberblick expander graphen" } @Book{Lei92, author = "T. Leighton", title = "Introduction to Parallel Algorithms and Architectures", publisher = "Morgan Kaufmann", year = 1992 } @Book{Lei92vorl, author = "T. Leighton", title = "Introduction to Parallel Algorithms and Architectures", publisher = "Morgan Kaufmann", year = 1992, note = "Algorithmen f{\"u}r Verbindungsnetzwerke" } @Book{Mat87, author = "F. Mattern", title = "Verteilte Basisalgorithmen", publisher = "Springer", year = 1987, number = 226, series = "Informatik-Fachberichte" } @Article{Mat87a, author = "F. Mattern", title = "Algorithms for Distributed Termination Detection", journal = "Distributed Computing", year = 1987, volume = 2, pages = "161--175" } @Article{MatMel89, author = "F. Mattern and H. Mehl", title = "{D}iskrete {S}imulation - {P}rinzipien und {P}robleme der {E}ffizienzsteigerung durch {P}arallelisierung", journal = "Informatik Spektrum", year = 1989, volume = 12, pages = "198--210" } @Article{Fuj91, author = "R. Fujimoto", title = "Parallel Discrete Event Simulation", journal = cacm, year = 1990, volume = 33, number = 10, pages = "30--53" } @Unpublished{RADF97, author = "R. R{\"o}nngren and R. Ayani and S. R. Das and R. M. Fujimoto", title = "Efficient Data Structures for Time Warp Event Sets on Shared Memory Systems", annote = "submitted to JPDC Special Issue on Data Structures, priority queue" } @TechReport{MilSto86, author = "R. Miller and Q. F. Stout", title = "Mesh Computer Algorithms for Computational Geometry", institution = "University of Buffalo", year = 1986, number = "86-18", note = "revised", annote = "Computational Geometry. Erste mir bekannte Nutzung von Hilber Kurven (hier als proximity ordering wiedererfunden). Sie wueschen sich einen Sortieralgorithmus auf dem Mesh. Scan ist wichtig. Von Schmeck bekommen. Erwaehnen ein Buch als to appear, das nicht auffindbar ist." } @Book{PreSha85, author = "F. P. Preparata and M. I. Shamos", title = "Computational Geometry", publisher = "Springer", year = 1985 } @TechReport{PruEtAl, author = "P. Prusinkiewicz and A. Lindenmayer and F. D. Fracchia", title = "Synthesis of space-filling curves on the sqare grid", institution = "University of Regina, Saskatchewan", year = 1989, annote = "Einige systematische Konstruktionsregeln" } @Book{PruLin91, author = "P. Prusinkiewicz and A. Lindenmayer", title = "The Algorithmic Beauty of Plants", publisher = "Springer", year = 1991, annote = "3D Hilbertkurve ueber Lindenmeyersystem" } @PhdThesis{Sin93, author = "J. P. Singh", title = "Parallel Hierarchical N-Body Methods and their Implications for Multiprocessors", type = "Ph.D. thesis", school = "Stanford University", year = 1993, annote = ">>Wiedererfindung<< von Hilbertkurven, getrennt gelagert." } @Article{MueRoo94, author = "D. M{\"u}ller-Wichards and W. R{\"o}nsch", title = "Scalability of algorithms: An analystic approch", journal = paco, year = 1995, volume = 21, pages = "937--952", annote = "ziemlich wirr" } @InProceedings{BCFV00, author = "P. Berenbrink and A. Czumaj and T. Friedetzky and N. D. Vvedenskaya", pages = "99--108", title = "On the Analysis of Infinite Parallel Job Allocation Processes via Differential Equations", booktitle = "11th ACM Symposium on Parallel Algorithms and Architectures", year = 2000 } @Article{VDK96, author = "N. D. Vvedenskaya and R. L. Dobrushin and F. I. Karpelevich", title = "Queueing System with Selection of the Shortest of Two Queues: An Asymptotic Approach", journal = "Problems of Information Transmission", year = 1996, volume = 32, number = 1, pages = "15--29" } @PhdThesis{Mit96phd, author = "M. Mitzenmacher", title = "The Power of Two Choices in Randomized Load Balancing", school = "UC Berkeley", year = 1996 } @InCollection{MitRicSit00, author = "M. Mitzenmacher and A. Richa and R. Sitaraman", title = "The power of two random choices: A survey of the techniques and results", booktitle = "Handbook of Randomized Computing", publisher = "Kluwer", year = 2000, editor = "P. Pardalos and S. Rajasekaran and J. Rolim" } %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Randomisierte Parallele Algorithmen allgemein @InProceedings{Mit98, author = "M. Mitzenmacher", title = "Analyses of Load Stealing Models Based on Differential Equations", pages = "212--221", booktitle = "10th ACM Symposium on Parallel Algorithms and Architectures", year = 1998 } @InProceedings{ABS98, author = "M. Adler and P. Berenbrink and K. Schr{\"o}der", title = "Analyzing an Infinite Parallel Job Allocation Process", booktitle = "6th European Symposium on Algorithms", pages = "417--428", year = 1998, number = 1461, series = "LNCS", publisher = "Springer" } @InProceedings{MFCS::AdlerBK1995, title = "Scheduling Parallel Communication: The {$h$}-relation Problem", author = "Micah Adler and John W. Byers and Richard M. Karp", editor = "Jir{\'\i} Wiedermann and Petr H{\'a}jek", booktitle = "Mathematical Foundations of Computer Science 1995, 20th International Symposium", address = "Prague, Czech Republic", month = "1~" # sep # "-- 28~" # aug, year = 1995, series = "lncs", volume = 969, publisher = "Springer", pages = "1--20", annote = "abstraktion fuer all-to-all" } @InProceedings{BarFra97, author = "Dominique Barth and Pierre Fraigniaud", title = "Approximation Algorithms for Structured Communication Problems", booktitle = "Proceedings of the 9th Annual {ACM} Symposium on Parallel Algorithms and Architectures", address = "Newport, Rhode Island", organization = "SIGACT/SIGARCH and EATCS", month = jun # " 22--25,", year = "1997", pages = "180--188", annote = "recht allgemeiner Ansatz fuer beliebige Netzwerke. telephone model, d.h. duplex mit einem Partner. Ergebnisse via simulation anderer Algorithmen. Eine runde kostet O(edge congestion + dilation)" } @InProceedings{AdlEtAl95, author = "M. Adler and S. Chakrabarti and M. Mitzenmacher and L. Rasmussen", title = "Parallel Randomized Load Balancing", booktitle = "ACM Symposium on the Theory of Computing", year = 1995, annote = "Randomisiertes Lastverteilen mit geringen Abweichungen durch wiederholtes zufaelliges Plazieren. Bringts nur fuer lange Nachrichten. Ergebins aus zitiertem paper koennte R. Luelings Problem des zufaelligen plazierens loesen. RDA, random allocation" } @InProceedings{Mit96, author = "Michael Mitzenmacher", title = "{Load balancing and density dependent jump Markov processes}", booktitle = "Proceedings of 37th Conference on Foundations of Computer Science", year = "1996", month = oct, pages = "213--222", keyword = "scheduling, load balance, random", abstract = "We provide a new approach for analyzing both static and dynamic randomized load balancing strategies. We demonstrate the approach by providing the first analysis of the following model: customers arrive as a Poisson stream of rate lambda /sub n/, lambda <1, at a collection of n servers. Each customer chooses some constant d servers independently and uniformly at random from the n servers, and waits for service at the one with the fewest customers. Customers are served according to the first-in first-out (FIFO) protocol, and the service time for a customer is exponentially distributed with mean 1. We call this problem the supermarket model. We wish to know how the system behaves, and in particular we are interested in the expected time a customer spends in the system in equilibrium. The model provides a good abstraction of a simple, efficient load balancing scheme in the setting where jobs arrive at a large system of parallel processors. This model appears more realistic than similar models studied previously, in that it is both dynamic and open: that is, customers arrive over time, and the number of customers is not fixed.", } @InProceedings{CFMMRSU98, author = "R. Cole and A. Frieze and B. M. Maggs and M. Mitzenmacher and A. W. Richa and R. K. Sitaraman and E. Upfal", title = "On balls and bins with deletions", booktitle = "2nd RANDOM", pages = "145--158", year = 1998, volume = 1518, series = "LNCS", publisher = "Springer" } @InProceedings{Scott91a, author = "David S. Scott", title = "Efficient All-to-All Communication Patterns in Hypercube and Mesh Topologies", booktitle = "Sixth Distributed Memory Computing Conference Proceedings", pages = "398--403", publisher = "IEEE", address = "Portland, OR", month = apr, year = "1991", keywords = "DMCC6, computation and algorithms, communication, Direct Exchange algorithms for Complete Exchange,", } @Article{Bruck:1997:EAA, author = "J. Bruck and Ching-Tien Ho and S. Kipnis and E. Upfal and D. Weathersby", title = "Efficient Algorithms for All-to-All Communications in Multiport Message-Passing Systems", journal = "IEEE Transactions on Parallel and Distributed Systems", volume = "8", number = "11", pages = "1143--1156", month = nov, year = "1997", coden = "ITDSEO", ISSN = "1045-9219", bibdate = "Fri Nov 6 12:31:15 MST 1998", url = "http://www.computer.org/tpds/td1997/l1143abs.htm; http://dlib.computer.org/td/books/td1997/pdf/l1143.pdf", acknowledgement = ack-nhfb, classification = "C4230 (Switching theory); C4240C (Computational complexity); C4240P (Parallel programming and algorithm theory); C5220P (Parallel architecture)", corpsource = "California Inst. of Technol., Pasadena, CA, USA", keywords = "all-to-all communications; communication bandwidth; communication complexity; communication start-up; complexity measures; concatenation; index; message passing; message-passing systems; multiport; parallel algorithms; point-to-point communication; sender-receiver pair", treatment = "T Theoretical or Mathematical", } @Article{WBPM97, author = "X. Wang and E. K. Blum and D. S. Parker and D. Massey", title = "The dance party problem and its application to collective communication in computer networks", journal = "Parallel Computing", year = 1997, volume = 23, number = 8, pages = "1141--1156" } @Article{HamHamKho95, author = "S. E. Hambrusch and F. Hameed and A. A. Khokar", title = "Communication Operations on coarse-grained mesh architectures", journal = "Parallel Computing", year = 1995, volume = 21, pages = "731--751", annote = "balanciertes all-to-all. benutzen one-factors" } @Article{AieEtAl91, author = "Aiello and Leighton and Maggs and Newman", title = "Fast Algorithms for Bit-Serial Routing on a Hypercube", journal = "Mathematical Systems Theory", volume = "24", pages = "253--271", year = "1991", abstract = "In this paper we describe an $O(\log N)$ bit-step randomized algorithm for bit-serial message routing on a hypercube. The result is asymptotically optimal, and improves upon the best previously known algorithms by a logarithmic factor. The result also solves the problem of on-line circuit switching in an $O(1)$-dilated hypercube (i.e., the problem of establishing edge-disjoint paths between the nodes of the dilated hypercube for any one-to-one mapping). Our algorithm is adaptive and we show that this is necessary to achieve the logarithmic speedup. We generalize the Borodin-Hopcroft lower bound on oblivious routing by proving that any randomized oblivious algorithm on a polylogarithmic degree network requires at least $\Omega(\log^2 N / \log\log N)$ bit steps with high probability for almost all permutations.", note = "Appeared also in 2nd Annual ACM Symposium on Parallel Algorithms and Architectures (SPAA 90)", annote = "Laut Alf laesst sich dieser Alg verwursten um T_req = O(max(log n, s(w))) fuer random polling zu erreichen." } @InProceedings{AuEtAl95, author = "V. Auletta and A. Negro and V. Scarano", title = "Fast Execution of Irregularly Structured Programs with Low Communication Frequency on the Hypercube", series = "LNCS", number = 980, booktitle = "Workshop on Algorithms for Irregularly Structured Problems", year = 1995, publisher = "Springer", address = "Lyon", annote = "Auch in ausfuehrlicher Variante. Ebenfalls fuer Special Issue TCS eingereicht" } @InProceedings{BlaRan93, author = "C. T. Blackston and A. Ranade", title = "{SnakeSort}: A Family of Simple Optimal Randomized Sorting Algorithms", number = "III", pages = "201--204", booktitle = "International Conference on Parallel Processing", year = 1993, address = "Boca Raton", annote = "Naive Algorithmen funktionieren mhw gut wenn nur genug Daten pro PE vorhanden, randomisiertes 01 Sortierlemma. " } @TechReport{BlaRan94, author = "D. T. Blackston and A. Ranade", title = "{SnakeSort}: A Family of Simple Optimal Randomized Sorting Algorithms", institution = "University of California Berkeley", year = 1994, annote = "Vollversion des Konferenzpapiers" } @Article{BluLei99, author = "R. D. Blumofe and C. E. Leiserson", title = "Scheduling multithreaded computations by work stealing", journal = "Journal of the ACM", volume = "46", number = "5", pages = "720--748", year = "1999", } @InProceedings{AroBluPla98, author = "N. S. Arora and R. D. Blumofe and C. G. Plaxton", title = "Thread Scheduling for Multiprogrammed Multiprocessors", pages = "119--129", address = "Puerto Vallarta, Mexico, June 28--July 2", publisher = "ACM, New York", booktitle = "10th ACM Symposium on Parallel Algorithms and Architectures", year = 1998 } @InProceedings{BluEtAl95, author = "R. D. Blumofe and C. Joerg and B. C. Kuszmaul and C. E. Leiserson and K. H. Randall and Y. Zhou", title = "Cilk: An Efficient Multithreaded Runtime System", pages = "207--216", booktitle = "Principles and Practice of Parallel Programming (PPoPP)", year = 1995, annote = "Anwendungen im wesentlichen Baumsuche.", address = "Santa Barbara, CA, 19--21 July", publisher = "ACM New York", } @InProceedings{BluEtAl96, author = "R. D. Blumofe and M. Frigo and C. F. Joerg and C. E. Leiserson and K. H. Randall", title = "An Analysis of Dag-Consistent Distributed Shared-Memory Algorithms", booktitle = "8th ACM Symposium on Parallel Algorithms and Architectures", year = 1996, pages = "297--308", address = "Padua, Italy, 24--26 June", publisher = "ACM, New York", } @InProceedings{Preis99, author = "Preis", title = "Linear Time $1/2$-Approximation Algorithm for Maximum Weighted Matching in General Graphs", booktitle = "Proc. 16th Ann. Symp. on Theoretical Aspects of Computer Science (STACS), LNCS 1563", year = "1999", pages = "259--269", } @Article{DH03a, author = "D. Drake and S. Hougardy", title = "A Simple Approximation Algorithm for the Weighted Matching Problem", journal = IPL, volume = "85", pages = "211--213", year = "2003", } @InProceedings{DH03b, author = "D. Drake and S. Hougardy", title = "Linear Time Local Improvements for Weighted Matchings in Graphs", booktitle = "International Workshop on Experimental and Efficient Algorithms (WEA), LNCS 2647", pages = "107--119", year = "2003", } @InProceedings{DH03c, author = "D. Drake and S. Hougardy", title = "Improved Linear Time Approximation Algorithms for Weighted Matchings", booktitle = "7th International Workshop on Randomization and Approximation Techniques in Computer Science (APPROX), LNCS 2764", pages = "14--23", year = "2003", } @techreport{PS04-tr, year = "2004", type = "Technical Report", number = "MPI-2-2004-1-002", institution = "Max Planck Institute for Computer Science", title = "A Simpler Linear Time {$2/3 - \epsilon$} Approximation for Maximum Weight Matching", bibdate = feb, author = "S. Pettie and P. Sanders", } @InProceedings{FLPR99, author = "M. Frigo and C. E. Leiserson and H. Prokop and S. Ramachandran", title = "Cache-Oblivious Algorithms", booktitle = "40th Symposium on Foundations of Computer Science", year = 1999, pages = "285--298" } @InProceedings{SenCha00, author = "S. Sen and S. Chatterjee", title = "Towards a Theory of Cache-Efficient Algorithms", booktitle = "11th ACM Symposium of Discrete Algorithms", pages = "829--838", year = 2000 } @Article{ZhiHer01, author = "V. V. Zhirnov and D. J. C. Herr", title = "New Frontiers: Self-Assembly and Nanoelectronics", journal = "IEEE Computer", year = 2001, volume = 34, number = 1, pages = "34--43" } @Unpublished{Tec00, author = "Lucent Technologies", title = "High Density Holographic Data Storage", note = "{\url{http://www.bell-labs.com/org/physicalsciences/projects/hdhds/1.html}}", year = 2000 } @InProceedings{BL94, author = "R. D. Blumofe and C. E. Leiserson", title = "Scheduling Multithreaded Computations by Work Stealing", booktitle = focs, pages = "356--368", address = "Santa Fe, NM, 20--22 November", publisher = "IEEE, Los Alamitos, CA", year = 1994 } @PhdThesis{Blu95, author = "R. D. Blumofe", title = "Executing Multithreaded Programs Efficiently", type = "Ph.D. thesis", school = "MIT", year = 1995 } @TechReport{BluEtAl94, author = "R. D. Blumofe and M. Halbherr and C. F. Joerg and B. C. Kuszmaul and C. E. Leiserson and P. Lisiecki and K. H. Randall and A. Shaw and Y. Zhou", title = "Cilk 1.1 Reference Manual", institution = "MIT", year = 1994, month = "September", annote = "vom WWW server. Interessanterweise deckt sich die Funktionalitaet nicht ganz mit dem Paper. Aber es gibt Beispiele, (Accus), bei denen der Fehler in der Analyse durchschlagen sollte." } @InCollection{ArgBro99, Year = 1999, Title = {On Showing Lower Bounds for External-Memory Computational Geometry Problems}, Annote = {In this paper, we consider lower bounds for external-memory computational geometry problems. We find that it is not quite clear which model of computation to use when considering such problems.}, Address = {Providence, RI}, Checked = {20020228jv}, Series = {{DIMACS} Series in Discrete Mathematics and Theoretical Computer Science}, Pages = {139--159}, Booktitle = {External Memory Algorithmss}, Publisher = {American Mathematical Society}, Author = {L. Arge and Bro Miltersen, P.}, Volume = 50} @InProceedings{Arg93, title = "A General Lower Bound on the {I/O}-Complexity of Comparison-based Algorithms", author = "Lars Arge and Mikael Knudsen and Kirsten Larsen", booktitle = "Algorithms and Data Structures, Third Workshop", editor = "Frank K. H. A. Dehne and J{\"o}rg-R{\"u}diger Sack and Nicola Santoro and Sue Whitesides", address = "Montr{\'e}al, Canada", month = "11--13~" # aug, year = "1993", series = "Lecture Notes in Computer Science", volume = "709", publisher = "Springer", ISBN = "ISBN 3-540-57155-8", pages = "83--94", } @PhdThesis{Arg96, author = "L. Arge", title = "Efficient External-Memory Data Structures and Applications", school = "University of Aarhus", year = 1996 } @InProceedings{ArgSamVit99, author = "L. Arge and V. Damoladas and J. S. Vitter", title = "On Two-Dimensional Indexability and Optimal Range Search Indexing", pages = "346--357", booktitle = "PODS", year = 1999, annote = "Lars hat hier drueber vorgetragen" } @Manual{Ven95, title = "{TPIE} User Manual and Reference", author = "D. E. Vengroff", organization = "Duke University", year = 1995, note = "\url{http://www.cs.duke.edu/~dev/tpie_home_page.html}" } @InProceedings{Arg95, author = "L. Arge", title = "{The Buffer Tree: A New Technique for Optimal I/O-Algorithms}", number = 955, series = "LNCS", pages = "334--345", booktitle = "4th Workshop on Algorithms and Data Structures", year = 1995, publisher = "Springer" } @InProceedings{Arg95www, author = "L. Arge", title = "The Buffer Tree: {A} New Technique for Optimal {I/O}-Algorithms", number = 955, series = "LNCS", pages = "334--345", booktitle = "4th WADS", year = 1995, note = "\htmladdnormallink{long version}{Arg95b.ps.gz}", publisher = "Springer" } @PhdThesis{NorbertThesis, author = "N. Zeh", title = "{I/O}-Efficient Algorithms for Shortest Path Related Problems", school = "Carleton University", year = 2002, address = "Ottawa, Canada" } @TechReport{WW03, author = "M. Wattenhofer and R. Wattenhofer", title = "Distributed Weighted Matching", institution = "ETH Z{\"{u}}rich", year = 2003, number = 420, note = "{\url{http://www.inf.ethz.ch/research/publications/data/tech-reports/4xx/420.ps}}" } @InProceedings{UehChe00, author = "Uehara and Chen", title = "Parallel Approximation Algorithms for Maximum Weighted Matching in General Graphs", booktitle = "IFIPTCS: IFIP International Conference on Theoretical Computer Science, LNCS", year = "2000", } @TechReport{KanMor02, author = "K. Kanemura and E. Moriya", title = "Parallel Approximation Algorithms and Average-Time Analysis for Maximum Weighted Matching in General Graphs", institution = "Advanced Research Institute for Science and Engineering", year = 2002, number = 3, comment = "average case, logDelta average time on EREW, linear work", address = "Waseda Univertiy, Japan", note = "{\url{http://www.rise.waseda.ac.jp/tech_repo/2002/03_e.html}}" } @InProceedings{GZ03, author = "B. Goethals and M. J. Zaki", title = "FIMI 03: Workshop on Frequent Itemset Mining Implementations", booktitle = " ", year = 2003, annote = "contains measurements on implementations" } @InProceedings{Goe04, author = "B. Goethals", title = "Memory Issues in Frequent Itemset Mining", booktitle = "SAC", year = 2004 } @TechReport{BFMZ04, author = "G. S. Brodal and R. Fagerberg and N. Zeh", title = "Cache-Oblivious Data Structures and Algorithms for Undirected Breadth-First Search and Shortest Paths", institution = "brics", year = 2004, number = "RS-04-2" } @InProceedings{ABT00, author = "L. Arge and G. Brodal and L. Toma", title = "On External Memory {MST}, {SSSP} and Multi-way Planar Graph Separation", booktitle = "7th Scandinavian Workshop on Algorithm Theory", pages = "433--447", year = 2000, volume = 1851, series = "LNCS", publisher = "Springer" } @InProceedings{BroKat98, author = "Gerth St{\o}lting Brodal and Jyrki Katajainen", booktitle = "6th Scandinavian Workshop on Algorithm Theory", publisher = "Springer {V}erlag, Berlin", number = 1432, pages = "107--118", series = "LNCS", title = "Worst-Case Efficient External-Memory Priority Queues", year = 1998 } @Article{WegTeu89, author = "L. M. Wegner and J. I. Teuhola", title = "The External Heapsort", journal = "IEEE Transactions on Software Engineering", year = 1989, volume = 15, number = 7, pages = "9--925", month = "July" } @Unpublished{Crau99, author = "A. Crauser", title = "Introduction to Magnetic Disc Drives", note = "SIG talk", year = 1999 } @Unpublished{CraFerMey97, author = "A. Crauser and P. Ferragina and U. Meyer", title = "Efficient Priority Queues in External Memory", note = "working paper", year = 1997, month = "October" } @InProceedings{KWCLC99, author = "S. Kuo and M. Winslett and Y. Cho and J. Lee and Y. Chen", title = "Efficient Input and Output for Scientific Simulations", pages = "33--44", booktitle = "IOPADS", year = 1999, annote = "Hilbertkurven fuer rectangular range queries bleibt hiner AsaEtAl95 zurueck?" } @InProceedings{AtaPra00, author = "Mikhail J. Atallah and Sunil Prabhakar", title = "(Almost) Optimal Parallel Block Access for Range Queries.", pages = "205--215", booktitle = "Proceedings of the Nineteenth {ACM} {SIGMOD}-{SIGACT}-{SIGART} Symposium on Principles of Database Systems ({PODS}-00)", month = may # "~15--17", publisher = "ACM Press", address = "N. Y.", year = "2000", annote = "Spezialfall von SanEgnKor00? Schlechtere bounds" } @Article{YanWan00, author = "Y. Yang and J. Wang", title = "Optimal All-to-All Personalized Exchange in Self-Routable Multistage Networks", journal = "IEEE Transactions on Parallel and Distributed Systems", volume = 11, number = 3, pages = "261--274", month = mar, year = 2000, coden = "ITDSEO", ISSN = "1045-9219", bibdate = "Thu Oct 12 18:48:32 MDT 2000", url = "http://www.computer.org/tpds/td2000/l0261abs.htm; http://dlib.computer.org/td/books/td2000/pdf/l0261.pdf", acknowledgement = ack-nhfb, } @InProceedings{ZWCL99, author = "Y. Zhou and L. Wang and D. W. Clark and K. Li", title = "Thread Scheduling for Our-of-Core Applications with Memory Server on Multicomputers", pages = "57--67", booktitle = "IOPADS", year = 1999, annote = "Speicher der anderen PEs als paging memory benutzen" } @InProceedings{AAK99, author = "S. Albers and S. Arora and S. Khanna", title = "Page replacement for general caching problems", booktitle = "10th ACM-SIAM Symposium Discrete Algorithms", pages = "31-40", year = 1999, annote = "variable page sizes" } @InProceedings{AlbBut03, author = "S. Albers and M. B{\"u}ttner", title = "Integrated Prefetching and Caching in Single and Parallel Disk Systems", booktitle = "15th ACM Symposium on Parallel Algorithms and Architectures", pages = "109--117", year = 2003 } @InProceedings{AlbGarLeo98, author = "S. Albers and N. Garg and S. Leonardi", title = "Minimizing Stall Time in Single and Parallel Disk Systems", pages = "454--462", ISBN = "0-89791-962-9", booktitle = "Proceedings of the 30th Annual {ACM} Symposium on Theory of Computing ({STOC}-98)", month = may # "~23--26", publisher = "ACM Press", address = "New York", year = "1998", } @Article{BlaKit91, author = "I. F. Blake and K. Kith", title = "On the Complet Weight Enumerator of Reed-Solomon Codes", journal = "SIAM Journal on Discrete Mathemtics", year = "1991", OPTkey = "", OPTvolume = "4", OPTnumber = "2", OPTpages = "164--181", OPTmonth = "", OPTnote = "", OPTannote = "" } @InProceedings{PSV92, author = "V. S. Pai and A. S. Schaeffer and P. J. Varman", title = "Markov Analysis of Multipe-Disk Prefetching Strategies for External Merging", booktitle = "ICPP", year = 1992, annote = "applied to external merge sort" } @InProceedings{PaiVar92, author = "V. S. Pai and P. J. Varman", title = "Prefetching with Multiple Disks for External Mergesort: Simulation and Analysis", booktitle = "ICDE", pages = "273--282", year = 1992 } @InProceedings{ErtKalVar00, author = "{\"O}. Ertug and M. Kallahalla and P. J. Varman", title = "Real Time Parallel Disk Scheduling for VBR Video Servers", booktitle = "CSI", year = 2000, address = "Chennai, India", note = "{\url{http://www.ece.rice.edu/~kalla/}}" } @inproceedings{KalVar01, author = {M. Kallahalla and P. J. Varman}, title = {Optimal prefetching and caching for parallel {I/O} systems}, booktitle = "13th Symposium on Parallel Algorithms and Architectures", pages = "219--228", year = 2001, } @Article{KalVar02, author = "M. Kallahalla and P. J. Varman", title = "{PC-OPT}: Optimal Offline Prefetching and Caching for Parallel {I/O} Systems", journal = "IEEE Transactions on Computers", year = 2002, number = 11, volume = 51, pages = "1333--1344" } @InProceedings{KalVar99, author = "M. Kallahalla and P. J. Varman", title = "Optimal Read-Once Parallel Disk Scheduling", pages = "68--77", booktitle = "6th Workshop on Input/Output in Parallel and Distributed Systems", year = 1999, annote = "no caches offline" } @Article{KWGH02, author = "S. Kirkpatrick and W. Wilcke and R. Garner and H. Huels", title = "Percolation in Storage Arrays", journal = "Physica A", year = 2002, note = "to appear", annote = "wann faellt das Ice Cube system aus?" } @InProceedings{MalSoi, author = "L. Malmi and E. Soisalon-Soininen", title = "Group Updates for Relaxed Height-Balanced Trees", pages = "358--367", booktitle = "PODS", year = 1999 } @Unpublished{LeuTsaTan99, author = "F. C. Leu and Y. T. Tsai and C. Y. Tang", title = "An Efficient External Sorting Algorithm", note = "two pass", year = 1999 } @InProceedings{BGHMSV99, author = "R. Barve and P. B. Gibbons and B. K. Hillyer and Y. Matias and E. Shriver and J. S. Vitter", title = "Round-like behavior in multiple disks on a bus", pages = "1--10", booktitle = "IOPADS", year = 1999, annote = "SCSI bus cannot be saturated with independent random accesses. No explanation!" } @InProceedings{SVV04, author = "R. Shah and P. J. Varman and J. S. Vitter", title = "Online algorithms for prefetching and caching on parallel disks", booktitle = "16th ACM Symposium on Parallel Algorithms and Architectures", pages = "255--264", year = 2004 } @InProceedings{BarVit99, author = "R. D. Barve and J. S. Vitter", title = "A Simple and Efficient Parallel Disk Merge Sort", booktitle = "11th ACM Symposium on Parallel Algorithms and Architectures", pages = "232--241", year = 1999 } @Article{BarGroVit97, author = "R. D. Barve and E. F. Grove and J. S. Vitter", title = "Simple Randomized Mergesort on Parallel Disks", journal = "Parallel Computing", year = 1997, volume = 23, number = 4, pages = "601--631", annote = "auch TR CS-1996-15, Duke" } @InProceedings{FJKT97, author = "R. Fadel and K. V. Jakobsen and J. Katajainen and J. Teuhola", title = "External heaps combined with effective buffering", volume = "19-2", series = "Australian Computer Science Communications", pages = "72--78", booktitle = "4th Australasian Theory Symposium", year = 1997, publisher = "Springer" } @InProceedings{AACHP97, author = "A. C. Arpaci-Dusseau et al.", title = "High-Performance Sorting on Networks of Workstations", pages = "243--254", booktitle = "{ACM} {SIGMOD}", series = "SIGMOD Record", volume = "26,2", year = "1997", } @InProceedings{HZ04, author = "N. J. A. Harvey and K. Zatloukal", title = "The Post-Order Heap", booktitle = "FUN with Algorithms", year = 2004, annote = "priority queue with O(1) amortized insert" } @InProceedings{GZ03, author = "J. Gao and L. Zhang", title = "Well-Separated Pair Decomposition for the Unit-Disk Graph Metric and its Applications", booktitle = "STOC", pages = "483--492", year = 2003 } @InProceedings{SVV04, author = "R. Shah and P. J. Varman and J. S. Vitter", title = "Online Algorithms for Prefetching and Caching on Parallel Disks", booktitle = "SPAA", year = 2004 } @Article{VarEtAl91, author = "Peter J. Varman and Scott D. Scheufler and Balakrishna R. Iyer and Gary R. Ricard", title = "Merging Multiple Lists on Hierarchical-Memory Multiprocessors", journal = "J. Par. {\&} Dist. Comp.", volume = "12", number = "2", pages = "171--177", year = "1991", coden = "JPDCER", ISSN = "0743-7315", bibdate = "Sat Apr 12 17:13:17 MDT 1997", acknowledgement = ack-nhfb, classification = "C4240 (Programming and algorithm theory)", corpsource = "Dept. of Electr. and Comput. Eng., Rice Univ., Houston, TX, USA", keywords = "computational complexity; data access costs; hierarchical-memory multiprocessors; merging lists; multiprocessor algorithm; multiway merging; parallel algorithms; partitioning algorithm; Sequent symmetry multiprocessor; sorted lists; time complexity", treatment = "T Theoretical or Mathematical", } @InProceedings{BFV04, author = "G. S. Brodal and R. Fagerberg and K. Vinther", title = "Engineering a Cache-Oblivious Sorting Algorithm", booktitle = "6th Workshop on Algorithm Engineering and Experiments", year = 2004 } @InProceedings{Tho03, author = "M. Thorup", title = "Integer priority queues with decrease key in constant time and the single source shortest paths problem", booktitle = "35th {ACM} Symposium on Theory of Computing", pages = "149--158", year = 2004 } @InProceedings{MTTZ04, author = "R. Mendelson and R. E. Tarjan, M. Thorup, U. Zwick", title = "Melding Priority Queues", booktitle = "9th Scandinavian Workshop on Algorithm Theory", pages = "223--235", year = 2004 } @InProceedings{HanTho02, author = "Y. Han, M. Thorup", title = "Integer Sorting in {$\Oh{n \sqrt{\log\log n}}$} Expected Time and Linear Space", booktitle = "42nd Symposium on Foundations of Computer Science", pages = "135--144", year = 2002 } @InProceedings{Bro96, author = "G. S. Brodal", title = "Priority Queues on Parallel Machines", booktitle = "5th Scandinavian Workshop on Algorithm Theory", number = 1097, series = "LNCS", year = 1996, publisher = "Springer", pages = "416--427" } @INCOLLECTION{Bro97, title = "Predecessor Queries in Dynamic Integer Sets", author = "G. S. Brodal", booktitle = "Proc. 14th Symposium on Theoretical Aspects of Computer Science", series = "Lecture Notes in Computer Science", number = "1200", publisher = "Springer {V}erlag, Berlin", pages = "21-32", year = "1997" } @InProceedings{BroEtAl97, author = "G. S. Brodal and J. L. Tr{\"a}ff and C. D. Zaroliagis", title = "A Parallel Priority Data Structure with Applications", booktitle = "11th International Parallel Processing Symposium", year = 1997, note = "to appear" } @Article{BroTraZar98, author = "G. S. Brodal and C. D. Zaroliagis and J. L. Tr{\"a}ff", title = "A Parallel Priority Data Structure with Applications", journal = "Journal Parallel and Distributed Processing, Special Issue on Parallel and Distributed Data Structures", year = 1998, volume = 49, number = 1, pages = "4--21", } @Article{BroTraZar98this, author = "G. S. Brodal and J. L. Tr{\"a}ff and C. D. Zaroliagis", title = "A Parallel Priority Data Structure with Applications", journal = jpdc, year = 1998, note = "This issue" } @Unpublished{BroEtAl97b, author = "G. S. Brodal and J. L. Tr{\"a}ff and C. D. Zaroliagis", title = "A Parallel Priority Queue with Constant Time Operations", note = "MPII", annote = "taucht in seiner Veroeffentlichungsliste nicht auf??" } @InProceedings{Che94, author = "J. Chen", title = "Parallel Heap Construction Using Multiple Selection", pages = "371--380", booktitle = "{CONPAR} {VAPP}", year = 1994, publisher = "Springer", annote = "CRCW; Wozu brauche ich heap construction?" } @InProceedings{ChiEtAl94, author = "D. D. Chinn and T. Leighton and M. Tompa", title = "Minimal Adaptive Routing on the Mesh with Bounded Queue Size", pages = "354--363", booktitle = spaa, year = 1994, address = "Cape May, New Jersey", annote = "Untere Schranken fur einfache Algorithmen" } @InProceedings{DeoPra90, author = "N. Deo and S. Prasad", title = "Parallel Heap", volume = "III", pages = "169--172", booktitle = "International Conference on Parallel Processing", year = 1990, annote = "EREW PRAM Frage: geht es nicht trivial auf Verbindungsnetzwerken?" } @Article{DeoPra92, author = "N. Deo and S. Prasad", title = "Parallel Heap: An Optimal Parallel Priority Queue", journal = "The Journal of Supercomputing", volume = "6", number = "1", pages = "87--98", month = mar, year = "1992", keywords = "parallel data structure, heaps, priority queue, optimal parallel algorithm, parallel random access machine, PRAM,", } @Article{OlaWen91, author = "S. Olariu and Z. Wen", title = "Optimal Parallel Initialization Algorithms for a Class of Priority Queues", journal = "IEEE Transactions on Parallel and Distributed Systems", year = 1991, volume = 2, number = 4, pages = "423--429", month = "October" } @TechReport{PinPuc91, author = "M. C. Pinotti and G Pucci", title = "Parallel Priority Queues", institution = "ICSI", year = 1991, number = "91-016", address = "Berkeley", annote = "Kennen Prasad Deo nicht. CREW, loeschen schneller, einfuegen gleich schnell. Benutzt Merge des neuen Knotens mit dem ganzen Pfad bis zur Wurzel. Deutlich einfacher als Prasad Deo.Es sieht so aus, als koennte man das ganze auch auf EREW wenn man loeschen so langsam macht wie einfuegen? Ein zusaetlicher loglog n Faktor ermoeglicht dann das ganze auf dem HC? (Leighton S. 642). Problem, wie kann man eine n log n und eine n sortierte Folge moeglichst schnell mergen?" } @TechReport{DasEtAl94, author = "S. K. Das and M. C. Pinotti and F. Sarkar", title = "Optimal Parallel Priority Queues in Distributed Memory Hypercubes", institution = "University of North Texas", year = 1994, number = "CRPDC-94-23", address = "Denton", month = "December" } @Article{DasPinSar96, author = "S. K. Das and M. C. Pinotti and F. Sarkar", title = "Optimal and Load Balanced Mapping of Parallel Priority Queues in Hypercubes", journal = tpds, year = 1996, volume = 7, number = 6, pages = "555--564", annote = "der Tr von Dez. 94, revised Nov. 95" } @InProceedings{DasPra94, author = "S. K. Das and F. Sarkar and S. K. Prasad", title = "Dynamic Load Balancing Algorithms for Optimistic Parallel Discrete Event Simulation", booktitle = "??", year = 1994, pages = "91--97", annote = "Keine PPQs" } @Article{PinPuc95, author = "M. C. Pinotti and G. Pucci", title = "Parallel algorithms for priority queue operation", journal = "Theoretical Computer Science", year = 1995, volume = 148, pages = "171--180", annote = "ein einzelnes Element so schnell wie moeglich rausholen" } @InProceedings{DasEtAl95, author = "S. K. Das and M. C. Pinotti and F. Sarkar", title = "Conflict-Free Path Access of Trees in Parallel Memory Systems With Applications to Distributed Heap Implementation", booktitle = icpp, year = 1995 } @InProceedings{RanEtAl94, author = "A. Ranade and S. Cheng and E. Deprit and J. Jones and S. Shih", title = "Parallelism and Locality in Priority Queues", pages = "97--103", booktitle = "Sixth IEEE Symposium on Parallel and Distributed Processing", year = 1994, month = "October", annote = "meshes" } @Article{DiaGraMor90, author = "P. Diaconis and R. L. Graham and J. A. Morrison", title = "Asymptotic Analysis of a Random Walk on a Hypercube with Many Dimensions", journal = "Random Structures and Algorithms", year = 1990, volume = 1, number = 1, pages = "51--72", annote = "Tbal in O(log n loglog n)" } @Article{DiaGra92, author = "P. Diaconis and R. L. Graham", title = "An affine walk on the hypercube", journal = "Computational and Applied Mathematics", year = 1992, volume = 41, pages = "215--235" } @InProceedings{GuPho94, author = "A. K. Gupta and A. G. Phoutiou", title = "Load Balanced Priority Queue Implementations on Distributed Memory Parallel Machines", number = 817, series = "LNCS", pages = "689--700", booktitle = "Sixth International Conference on Parallel Architectures and Languages Europe", year = 1994, publisher = "Springer", address = "Athens", month = "July" } @InProceedings{DonEtAl96, author = "E. de Doncker and P. Ealy and A. Gupta", title = "Two Methods for Load Balanced Distributed Adaptive Integration", pages = "562--570", booktitle = "HPCN Europe", year = 1996, OPTaddress = "Br{\"u}ssel", annote = "Interessante Anwendung fuer parallele priority queue" } @InProceedings{Man95, author = "B. Mans", title = "Portable Distributed Priority Queues with MPI", booktitle = "International Conference on High Performance Computing", year = 1995, annote = "Bettet PE Baum ein => hot spot T3D impl. Branch and bound als Testanwendung. Event set Anwendungsmodell: Queue anfangs voll. Jedes PE entnimmt elemnt und fuegt zufaelliges neues ein. Leider wird nicht ganz verraten was gemessen wird. Gesamtdurchsatz sinkt mit Anzahl PEs !" } @InProceedings{DioEtAl94, author = "M. Dion and M. Gengler and S. Ubeda", title = "Comparing two Probabilistic Models of the Computational Complexity of the Branch and Bound Algorithm", pages = "359--370", booktitle = "{CONPAR/VAPP}", year = 1994, publisher = "Springer", address = "Linz", annote = "modelliere Differenzen zwischen Knotenschranken als identisch verteilte unabh ZVA. Dann wird magisch diskretiesiert und es stellt sich heraus, das die Anzahl Knoten mit gleicher Bewertung exponentiell mit der Suchbaumtiefe waechst. B&B nutzt das aus indem nur Knoten mit gleicher Bewertung parallel expandiert werden. Die Leute scheinen noch nie von IDA* gehoert zu haben. (waere wohl oft effizienter). Die herleitungen scheinen Fehler zu enthalten." } @InProceedings{DG96, author = "C. G. Diderich and M. Gengler", title = "Solving Traveling Salesman Problems Using a Parallel Synchronized Branch and Bound Algorithm", pages = "633--638", booktitle = "HPCN Europe", year = 1996, address = "Br{\"u}ssel", annote = "bis zu 256 PEs, schlecht, aehnlicher seq. Ansatz wie Paderborner, LV wie gehabt" } @InProceedings{WooYan00, author = "Sung-Ho Woo and Sung-Bong Yang", title = "An Improved Nework Clustering Method for I/O Efficient Query Processing", booktitle = "ACM GIS", pages = "62--68", year = 2000, annote = "simple heuristics. needs BFS" } @Unpublished{Ten97, author = "S.-H. Teng", title = " Coarsening, Sampling, and Smoothing: Elements of the Multilevel Method ", note = "{\url{http://www-sal.cs.uiuc.edu/~steng/multilevel.ps}}" } @InProceedings{SpiTen96, author = "D. A. Spielman and S.-H. Teng", title = "Spectral Partitioning Works: Planar graphs and finite element meshes", booktitle = "37th Conference on Foundations of Computer Science", pages = "96--105", year = 1996 } @InProceedings{FelSgaEtAl91, author = "A. Feldmann and J. Sgall and S. Teng", title = "Dynamic Scheduling on Parallel Machines", pages = "111--120", booktitle = focs, year = 1991, publisher = "IEEE", annote = "nongreedy Heuristing fuer Prozessorzuteilung auf 2D Gitter." } @Article{GuGu94, author = "Q. P. Gu and J. G. Gu", title = "Algorithms and Average Time Bounds of Sorting on a Mesh-Connected Computer", journal = tpds, year = 1994, volume = 5, number = 3, pages = "308--315", annote = "Sehr effiziente Sorieralgorithmen fuer Gitter fuer versch. Knoennumerierungen." } @Article{GupEtAl94, author = "R. Gupta and S. A. Smolka and S. Bhaskar", title = "On Randomization in Sequential and Distributed Algorithms", journal = acmcs, year = 1994, volume = 26, number = 1, pages = "7--86", annote = "average time ungleich expected time, whp als 1-1/n definiert, almost shurely als 1-1/2^n^c definiert, random NC ungleich NC? universelles hashing, perfect hashing, Diskussion der Quellen von Zufallsbits. verloren?" } @InProceedings{PagRod01, author = "Pagh and Rodler", series = "LNCS", publisher = "Springer", volume = "2161", title = "Cuckoo Hashing", booktitle = "ESA: Annual European Symposium on Algorithms", year = "2001", } @InProceedings{Pag99, author = "R. Pagh", title = "Gash and Displace: Efficient Evaluation of Minmal Perfect Hash Functions", booktitle = "WADS", pages = "49--54", year = 1999, volume = 1663, series = "LNCS", publisher = "Springer" } @Article{AHNR98, author = "A. Andersson and T. Hagerup and S. Nilsson and R. Raman", title = "Sorting in linear time?", journal = "Journal of Computer and System Sciences", year = 1998, pages = "74--93" } @Article{HagRue89, author = "T. Hagerup and C. R{\"u}b", title = "Optimal merging and sorting on the {EREW-PRAM}", journal = "Information Processing Letters", year = 1989, volume = 33, pages = "181--185" } @Article{HagRue, author = "T. Hagerup and C. R{\"u}b", title = "A Guided Tour of Chernoff Bounds", journal = ipl, year = 1990, volume = 33, pages = "305--308" } @InProceedings{Hag91, author = "T. Hagerup", title = "Fast Parallel Generation of Random Permutations", booktitle = "International Colloquium on Automata, Languages and Programming", year = 1991 } @InProceedings{Hag92, author = "T. Hagerup", title = "The Log-Star Revolution", pages = "259--280", ISBN = "3-540-55210-3", editor = "Alain Finkel and Matthias Jantzen", booktitle = "Proceedings of Symposion on Theoretical Aspects of Computer Science ({STACS} '92)", month = feb, series = "LNCS", number = "577", publisher = "Springer", year = "1992", } @Article{Rag88, author = "P. Raghavan", title = "Probabilistic Construction of Deterministic Algorithms: Approximating Packing Integer Programs", journal = "Journal of Computer and System Sciences", year = 1988, volume = 37, pages = "130--143", annote = "weighted Chernoff bound" } @Book{BorYan98, author = "A. Borodin and R. El-Yaniv", title = "Online Computation and Competitive Analysis", publisher = "Cambridge University Press", year = "1998", address = "Cambridge", language = "english", } @InProceedings{BKRSW96, author = "A. Borodin and J. Kleinberg and P. Raghavan and M. Sudan and D. P. Williamson", title = "Adversarial Queing Theory", booktitle = "28th Annual {ACM} Symposium on Theory of Computing", pages = "376--385", year = 1996 } @InProceedings{AKOR98, author = "W. Aiello and E. Kushilevitz and R. Ostrovsky and A. Ros{\'e}n", title = "Adaptiv Packet Routing for Bursty Adversarial Traffic", booktitle = "30th Annual {ACM} Symposium on Theory of Computing", pages = "359--368", year = 1998 } @InBook{Pet95, author = "V. V. Petrov", title = "Limit Theorems of Probability Theory", publisher = "Clarendon Press", year = 1995, pages = "167ff", address = "Oxford", annote = "genaue Aussagen ueber Konvergenzgeschwindigkeit der Normalapproximation. von Hannah Bast" } @ARTICLE{BasHag95, AUTHOR = {H. Bast and T. Hagerup}, TITLE = {Fast Parallel Space Allocation, Estimation and Integer Sorting}, YEAR = {1995}, JOURNAL = {Information and Computation}, VOLUME = {123}, PAGES = {72 - 110}, } @InProceedings{Bas98, author = "H. Bast", title = "Dynamic Scheduling with Incomplete Information", booktitle = "10th ACM Symposium on Parallel Algorithms and Architectures" } @InProceedings{BasHag91, author = "H. Bast and T. Hagerup", title = "Fast and Reliable Parallel Hashing", pages = "50--61", booktitle = "3rd Symposium on Parallel Algorithms and Architectures", year = 1991 } @InProceedings{Nar99, author = "Girija J. Narlikar", title = "Scheduling Threads for Low Space Requirement and Good Locality", booktitle = "Proceedings of the 11th Annual {ACM} Symposium on Parallel Algorithms and Architectures", address = "Saint-Malo, France", month = jun # " 27--30,", year = "1999", pages = "83--95", publisher = "ACM, New York", } @InProceedings{HuCho83, author = "J. S. Huang and Y. C. Chow", title = "Parallel sorting and data partitioning", booktitle = "7th IEEE International Computer Software and Applications Conference", pages = "627--631", year = 1983 } @InProceedings{Aga96, author = "R. Agarwal", title = "A super scalar sort algorithm for {RISC} processors", booktitle = "{ACM SIGMOD} Int. Conf. on Management of Data", pages = "240--246", year = 1996, annote = "msd radix sort mentions TLB and branches" } @InProceedings{BleEtAl91, author = "G. E. Blelloch and C. E. Leiserson and B. M. Maggs and C. G. Plaxton and S. J. Smith and M. Zagha", title = "A comparison of sorting algorithms for the Connection Machine {CM-2}.", booktitle = spaa, year = 1991, pages = "3--16" } @InProceedings{BMW03, author = "G. E. Blelloch and B. M. Maggs and S. L. M. Woo", title = "Space-efficient finger search on degree-balanced search trees", booktitle = "14th Symposium on Discrete algorithms", pages = "374--383 ", year = 2003, annote = "Einsparung von Backpointern and level links durch komplexere Iteratoren" } @InCollection{MonLue, author = "B. Monien and R. L{\"u}ling", title = "Mapping und Lastverteilung in parallelen Systemen", booktitle = "??" } @InProceedings{DieEtAl94, author = "R. Diekmann and J. Gehring and R. L{\"u}ling and B. Monien and M. N{\"u}bel and R. Wanka", title = "Sorting Large Data Sets on a Massively Parallel System", booktitle = "6th IEEE Symposium on Parallel and Distributed Processing", year = 1994, pages = "2--9" } @InProceedings{HigEtAl92, author = "W. L. Hightower and J. F. Prins and J. H. Reif", title = "Implementations of Randomized Sorting on Large Parallel Machines", pages = "158--167", booktitle = spaa, year = 1992, annote = "Grosse Datenmengen werden auf MasPar sortiert. Samples muessen recht gross gewaehlt werden damit der Speicher nicht zu ungleichmaessig ausgelastet wird. Analyse wird einschliesslich der zu betrachtenden Konstanten betrieben. Beispiel wo Fehlschlagsw beliebig klein aber mit festem Exponenten ist. Splitter directed routing auf Meshes." } @InProceedings{Ier94, author = "D. Ierardi", title = "2d-Bubblesorting in Average Time {$O(\sqrt{N\lg N}$)}", booktitle = spaa, pages = "36--47", year = 1994, annote = "whp und average case, Mir die liebste Def. von whp, wichtig ist, das der worst case oft bei ungleicher verteilung von 0 und 1 auftritt. Andere Form des randomisierten 0-1 Sortierlemmas. Anders Beispiel fuer max Problem" } @Article{LanEtAl85, author = "H. Lang and M. Schimmler and H. Schmeck and H. Schr{\"o}der", title = "Systolic Sorting on a Mesh-Connected Network", journal = ietc, year = 1985, volume = 34, number = 7, pages = "652--658" } @InProceedings{LeiEtAl89, author = "T. Leighton and M. Newman and A. G. Ranade and E. Schwabe", title = "Dynamic Tree Embeddings in Butterflies and Hypercubes", booktitle = spaa, pages = "224--234", year = 1989, annote = "Loose end: Lower bound fuer det DLB?", address = "Santa Fe, NM, 18--21 June", publisher = "ACM, New York", } @InProceedings{LiSev94, author = "H. Li and K. C. Sevcik", title = "Parallel Sorting by Overpartitioning", pages = "46--56", booktitle = spaa, year = 1994, address = "Cape May, New Jersey", annote = "sample sort mit kP pivots. Sample wird seriell sortiert, dann wird globale nach Langen sortierte Liste der Segmente angelegt. angelegt und round robin abgeholt. Interessanter Verweis det. sample-sort Variante: sortiere lokal, bestimmt P lokale pivots sortiere die P^2 lokalen Pivots global und waehle dann P pivots aequidistant. Max Faktor 2 Overhead. Frage: was passiert wenn man aus denen wieder nur PlogP Elemente auswaehlt?" } @TechReport{AluEtAl96, author = "S. Aluru and S. Goil and S. Ranka", title = "Concatenated Parallelism: A Technique for Efficient Parallel Divide and Conquer", institution = "NPAC Syracuse University", year = 1996, number = "SCCS-759", annote = "deterministische LV fuer divide and conquer wenn man Teilproblemgroessen kennt. Overpartitioning. Quicksort, ..." } @Article{RanWanKum, author = "S. Ranka and J. Wang and M. Kumar", title = "Irregular Personalized Communication on Distributed Memory Machines", journal = jpdc, year = 1995, volume = 25, pages = "58--71", annote = "betonen den Fall weniger Nachriten CM5 orientiert. RS_NH ist interssanter Alg: bestimme Chunk size und berechne Folge von Permuationenen dieser Chunk size mit random und greedy Elementen. Analyse nur experimentell wird als schwierig bezeichnet." } @inproceedings{AluEtAl96a, title = "Concatenated Parallelism: A Technique for Efficient Parallel Divide and Conquer", author = "Sanjay Goil and Srinivas Aluru and Sanjay Ranka", booktitle = "Proceedings of the 8th IEEE Symposium on Parallel and Distributed Processing", pages = "488--495", year = 1996} @InProceedings{BurKar03, author = "Stefan Burkhardt and Juha K�kk�nen", title = "Fast lightweight suffix array construction and checking", booktitle = "14th Symposium on Combinatorial Pattern Matching", year = 2003, series = "LNCS", publisher = "Springer", note = "to appear" } @InProceedings{Har96, author = "J. Hardwick", title = "An Efficient Implementation of Nested Data Parallelism for Irregurlar Divide-and-Conquer Algorithms", booktitle = "Workshop on High-Level Programming Models and Supportive Environments", year = 1996, address = "Honolulu, Hawaii", annote = "Qucksort mit generischem Lastverteilungsverfahren" } @InCollection{Apostolico85, author = "Apostolico", title = "The Myriad Virtues of Subword Trees", booktitle = "Alberto Apostolico and Zvi Galil, Combinatorial Algorithms on Words, NATO ISI Series, Springer-Verlag", year = 1985, annote = "suffix tree" } @Article{McCreight:1976:SES, author = "Edward M. McCreight", title = "A Space-Economical Suffix Tree Construction Algorithm", journal = "Journal of the ACM", volume = "23", number = "2", pages = "262--272", month = apr, year = "1976", coden = "JACOAH", ISSN = "0004-5411", bibdate = "Wed Jan 15 18:12:53 MST 1997", abstract = "A new algorithm is presented for constructing auxiliary digital search trees to aid in exact-match substring searching. This algorithm has the same asymptotic running time bound as previously published algorithms, but is more economical in space. Some implementation considerations are discussed, and new work on the modification of these search trees in response to incremental changes in the strings they index (the update problem) is presented.", acknowledgement = ack-nhfb, classification = "723; 901", comment = "Algorithms to build, use, and modify suffix tree are presented. The advantage of this algorithm over other linear time algorithms to perform similar tasks is that this algorithm uses less space. This seems to the primary reference for suffix trees.", journalabr = "J Assoc Comput Mach", keywords = "computer programming; information science --- Information Retrieval", } @InProceedings{MutRaj98, author = "S. Muthukrishnan and R. Rajaraman", title = "An Adversarial Model for Distributed Dynamic Load Balancing", pages = "47--54", booktitle = "10th ACM Symposium on Parallel Algorithms and Architectures", annote = "Adversay model for token distribution on a network" } @InProceedings{GMR92, author = "L. Guibas and J. Mitchell and T. Roos", title = "Voronoi diagrams of moving points in the plane", pages = "113--125", ISBN = "3-540-55121-2", editor = "Gunther Schmidt and Rudolf Berghammer", booktitle = "Proceedings on Graph--Theoretic Concepts in Computer Science ({WG} '91)", month = jun, series = "LNCS", volume = "570", publisher = "Springer", address = "Berlin, Germany", year = "1992", } @Article{CarWeg79, author = "J. Lawrence Carter and Mark N. Wegman", title = "Universal Classes of Hash Functions", journal = "Journal of Computer and System Sciences", volume = "18", number = "2", pages = "143--154", month = apr, year = "1979", coden = "JCSSBM", ISSN = "0022-0000", bibdate = "Sat Jan 25 17:38:12 MST 1997", abstract = "An input independent average linear time algorithm for storage and retrieval on keys is given. The algorithm makes a random choice of hash function from a suitable class of hash functions. Given any sequence of inputs the expected time (averaging over all functions in the class) to store and retrieve elements is linear in the length of the sequence. The number of references to the data base required by the algorithm for any input is extremely close to the theoretical minimum for any possible hash function with randomly distributed inputs. Three suitable classes of hash functions are presented which also can be evaluated rapidly. The ability to analyze the cost of storage and retrieval without worrying about the distribution of the input allows as corollaries improvements on the bounds of several algorithms.", acknowledgement = ack-nhfb, classification = "723", journalabr = "J Comput Syst Sci", keywords = "computer programming; skew", } @InProceedings{DieMey93, author = "M. Dietzfelbinger and Meyer auf der Heide, F.", title = "Simple, Efficient Shared Memory Simulations", booktitle = "5th {ACM} Symposium on Parallel Algorithms and Architectures", address = "Velen, Germany", organization = "SIGACT and SIGARCH", month = jun # " 30--" # jul # " 2,", year = "1993", pages = "110--119", } @Article{DKMMRT94, author = "Martin Dietzfelbinger and Anna Karlin and Kurt Mehlhorn and Friedhelm Meyer auf der Heide and Hans Rohnert and Robert E. Tarjan", title = "Dynamic Perfect Hashing: Upper and Lower Bounds", journal = "SIAM Journal on Computing", volume = "23", number = "4", pages = "738--761", month = aug, year = "1994", coden = "SMJCAT", ISSN = "0097-5397 (print), 1095-7111 (electronic)", mrclass = "68P10 (68Q20)", mrnumber = "95c:68055", bibdate = "Sat Dec 5 17:26:53 MST 1998", url = "http://epubs.siam.org/sam-bin/dbq/article/19409", acknowledgement = ack-nhfb, } @Article{SchSieSri95, author = "J. P. Schmidt and A. Siegel and A. Srinivasan", title = "Chernoff-Hoeffding Bounds for Applications with Limited Independence", journal = "SIAM Journal of Discrete Mathematics", year = 1995, volume = 8, number = 2, pages = "223--250", annote = "laut M. Dietzfelbinger wichtiges Ergebnis zur Verwendung von universal hashing methoden" } @Article{JACM::MackenziePR1998, title = "On Contention Resolution Protocols and Associated Probabilistic Phenomena", author = "P. D. Mackenzie and C. G. Plaxton and R. Rajaraman", area = "Parallel Computation", journal = "Journal of the ACM", pages = "324--378", month = mar, year = 1998, volume = 45, number = 2, keywords = "Parallel computation, hash functions, emulation protocols", general-terms = "Algorithms, Theory", cr-categories = "F.1.2[parallelism and concurrency]; F.2.2", preliminary = "stoc::MackenziePR1994", references = "\cite{JCSS::AlonBLP1991} \cite{JCSS::CarterW1979} \cite{SPAA::DietzfelbingerH1993} \cite{SPAA::Gereb-GrausT1992} \cite{SPAA::GoldbergJLR1993} \cite{SPAA::GoldbergMR1994} \cite{JACM::GreenbergFL1987} \cite{JACM::GreenbergW1985} \cite{FOCS::GreenbergL1985} \cite{STOC::KarpLH1992} \cite{IEEETIT::KomlosG1985} \cite{CACM::MetcalfeB1976} \cite{STACS::HeideSS1995} \cite{FOCS::Siegel1989} \cite{JACM::UpfalW1987} \cite{FOCS::Yao1983}", annote= "fast das gleiche wie ein STACS95 paper von FMadH (loglog n) . allgemeines r aus R Problem wird betrachtet. RDA, " } @InProceedings{BDLMMNV02, author = "L. Becchetti and S. Diggavi and S. Leonardi and A. Marchetti-Spaccamela and S. Muthukrishnan and T. Nandagopal and A. Vitaletti", title = "Parallel Scheduling Problems in Next Generation Wireless Networks", booktitle = "SPAA", pages = "238--247", year = 2002, annote = "ressource augmented competitive analysis, minimizing maximal responce time, assigne both codes and data rates, QOS" } @InProceedings{MSVG02, author = "Meyer auf der Heide, F. and C. Schindelhauer and K. Volbert and M. Gr{\"u}newald", title = "Energy, Congestion and Dilation in Radio Networks", booktitle = "SPAA", pages = "230--237", year = 2002, annote = "behaupten MST seien energieoptimal" } @InProceedings{GhoEtAl95, author = "B. Ghosh and F. T. Leighton and B. M. Maggs and S. Muthukrishnan and C. G. Plaxton and R. Rajaraman and A. W. Richa and T. E. Tarjan and D. Zuckerman", title = "Tight Analyses of Two Local Load Balancing Algorithms", booktitle = stoc, year = 1995, annote = "preprint, benutzen Random matching. Funktioniert besonders gut fuer expandergraphen. " } @InProceedings{GGP95, author = "S Ghosh and A Gupta and SV Pemmaraju", title = "A self-stabilizing algorithm for the maximum flow problem", booktitle = "Proceedings of the IEEE 14th Annual International Phoenix Conference on Computers and Communication", year = "1995", pages = "8--14", annote = "habe version aus Distributed Computing (1997)10" } @InProceedings{GehPlaRaj97, author = "Gehrke and Plaxton and Rajaraman", title = "Rapid Convergence of a Local Load Balancing Algorithm for Asynchronous Rings", booktitle = "WDAG: International Workshop on Distributed Algorithms", series = "LNCS", number = 1320, publisher = "LNCS, Springer-Verlag", year = 1997, annote = "unser nearest neighbor algorithmus" } @Article{SleTar83, author = "D. D. Sleator and R. E. Tarjan", title = "A Data Structure for Dynamic Trees", journal = "Journal of Computer and System Sciences", year = "1983", volume = "26", number = "3", mon = jun, pages = "362--391", } @Article{DriEtAl88, author = "J. R. Driscoll and H. N. Gabow and R. Shrairman and R. E. Tarjan", title = "Relaxed Heaps: An Alternative to {F}ibonacci Heaps with Applications to Parallel Computation", journal = cacm, year = 1988, volume = 31, number = 11, pages = "1343--1354" } @InProceedings{MunRan99, AUTHOR = {K. Munagala and A. Ranade}, TITLE = {{I/O}-complexity of graph algorithms}, YEAR = {1999}, booktitle = "Proc. 10th Symp. on Discrete Algorithms", pages = {687--694}, publisher = {ACM-SIAM} } @InProceedings{KS96, author = "V. Kumar and E. J. Schwabe", title = "Improved Algorithms and Data Structures for Solving Graph Problems in External Memory", pages = "169--177", booktitle = "Proc. 8th Symp. on Parallel and Distrib. Processing", publisher = "IEEE", year = "1996", } @Article{YDL91, author = "S. B. Yang, Sudarshan K. Dhall, S. Lakshmivarahan", title = "An Improved Maximal Matching Algorithm", journal = "Parallel Processing Letters", year = 1991, volume = 1 } @Article{AbeBuc02, author = "J. Abello and A. L. Buchsbaum and J. R. Westbrook", title = "A Functional Approach to External Graph Algorithms", journal = "Algorithmica", year = 2002, volume = 32, pages = "437-458", annote = "semi external MST" } @InProceedings{BGVW00, AUTHOR = {A. Buchsbaum and M. Goldwasser and S. Venkatasubramanian and J. Westbrook}, TITLE = {On external memory graph traversal}, YEAR = {2000}, booktitle = "Proc. 11th Symp. on Discrete Algorithms", pages = {859--860}, publisher = {ACM-SIAM} } @InProceedings{ArToVi00, AUTHOR = {L. Arge and L. Toma and J. S. Vitter}, TITLE = {{I/O}-efficient algorithms for problems on grid-based terrains}, YEAR = {2000}, booktitle = "Proc. Workshop on Algorithm Engineering and Experiments (ALENEX)", } @InProceedings{RKU00, author = "A. Ranade and S. Kothari and R. Udupa", title = "Register Efficient Mergesorting", booktitle = "High Performance Computing --- HiPC", pages = "96--103", year = 2000, volume = 1970, series = "LNCS", publisher = "Springer" } @Article{WACV02, author = "R. Wickremesinghe and L. Arge and J. S. Chase and J. S. Vitter", title = "Efficient Sorting Using Registers and Caches", journal = "ACM Journal of Experimental Algorithmics", year = 2002, volume = 7, number = 9 } @InProceedings{ArBrTo00, author = "L. Arge and G. Brodal and L. Toma", title = "On External-Memory {MST}, {SSSP} and multi-way Planar Graph Separation", booktitle = "Proc. 8th Scand.Workshop on Alg. Theory", publisher = "Springer", series = "LNCS", year = 2000 } @InProceedings{MahZeh99, author = "A. Maheshwari and N. Zeh.", title = "External Memory Algorithms for Outerplanar Graphs", pages = "307--316", booktitle = "Proc. 10th Intern. Symp. on Algorithms and Computations", series = "LNCS", volume = "1741", publisher = "Springer", year = "1999", } @ARTICLE{ZhaNoo98, AUTHOR = {Zhan, F. B. and Noon, C. E.}, TITLE = {Shortest path algorithms: {An} evaluation using real road networks}, YEAR = {1998}, JOURNAL = {Transportation Science}, VOLUME = {32}, PAGES = {65--73}, BIBTYPE = {ARTICLE}, } @ARTICLE{CheGolRad96, AUTHOR = {Cherkassky, B. V. and Goldberg, A. V. and Radzik, T.}, TITLE = {Shortest path algorithms: {Theory} and experimental evaluation }, YEAR = {1996}, JOURNAL = {Math.\ Programming}, VOLUME = {73}, PAGES = {129--174}, LOCATION = {priebe's library}, BIBTYPE = {ARTICLE}, } @Article{Dij59, author = "E. W. Dijkstra", title = "A note on two problems in connexion with graphs.", journal = "Numerische Mathematik", volume = "1", pages = "269--271", year = "1959", keywords = "weighted, graph, graphs, all pairs shortest paths, path, minimal, minimum, weight, closure, spanning tree, connection, SSSP", } @Article{Tho99, author = "Mikkel Thorup", title = "Undirected Single Source Shortest Paths in Linear Time", journal = "Journal of the ACM", year = 1999, volume = 46, pages = "362--394" } @InProceedings{Tho97, author = "Mikkel Thorup", title = "Undirected Single Source Shortest Paths in Linear Time", booktitle = focs, year = 1997 } @InProceedings{Tho96, author = "Mikkel Thorup", title = "On {RAM} Priority Queues", pages = "59--67", ISBN = "0-89871-366-8", booktitle = "Proceedings of the Seventh Annual {ACM}-{SIAM} Symposium on Discrete Algorithms", month = "28--30*" # jan, publisher = "ACM/SIAM", address = "New York/Philadelphia", year = "1996", } @Article{Kle94, author = "P. N. Klein", title = "A data structure for bicategories, with application to speeding up an approximation algorithm", journal = "Information Processing Letters", year = 1994, volume = 52, pages = "303--307", annote = "network design, non-fixed point-to-point problem, netral forest problem" } @InProceedings{KLA+01, author = "T. Kasai and G. Lee and H. Arimura and S. Arikawa and K. Park", title = "Linear-Time Longest-Common-Prefix Computation in Suffix Arrays and Its Applications", booktitle = proc # "12th " # cpm, series = lncs, volume = "2089", publisher = springer, pages = "181--192", year = "2001", } @Article{BDTW, author = "J. L. Balcazar and Y. Dai and J. Tanaka and O. Watanabe", title = "Provably Fast Training for Support Vector Machines", journal = "dam", year = "???" } @Article{HMKKESL04, author = "T. Ho and M. Medard and R. Koetter and D. R. Karger and M. Effros and J. Shi and B. Leong", title = "Towards a Random Operation of Networks", journal = "submitted", year = 2004, annote = "journal version of two isit papers?" } @Article{CLC82, author = "F. Y. Chin and J. Lam and I-N. Chen", title = "Efficient Parallel Algorithms for Some Graph Problems", journal = "cacm", year = 1982, annote = "conncted components and mst dense graphs only?" } @InProceedings{KR04, author = "D. R. Karger and M. Ruhl", title = "Simple Efficient Load Balancing Algorithms for Peer-to-Peer Systems", booktitle = "SPAA", year = 2004 } @InProceedings{STOC98*69, author = "David R. Karger and Matthew S. Levine", title = "Finding Maximum Flows in Simple Undirected Graphs is Easier Than Bipartite Matching", pages = "69--78", ISBN = "0-89791-962-9", booktitle = "Proceedings of the 30th Annual {ACM} Symposium on Theory of Computing ({STOC}-98)", month = may # "23--26~", publisher = "ACM Press", address = "New York", year = "1998", } @InProceedings{GhoMutSch96, author = "B. Ghosh and S. Muthukrishnan and M. H. Schultz", title = "First and second order diffusive methods for rapid, coarse, distributed load balancing", booktitle = spaa, year = 1996, pages = "72--81" } @Article{LeiEtAl94, author = "F. T. Leighton and B. M. Maggs and A. G. Ranade and S. B. Rao", title = "Randomized Routing and Sorting on Fixed-Connection Networks", journal = "Journal of Algorithms", year = 1994, volume = 17, pages = "157--205" } @Unpublished{Mag01, author = "B. Maggs", title = "Challenges in Building a Reliable System of Tens of Thousandes of Servers", note = "Akamai Technologies, mini course at ADFOCS", year = 2001 } @InProceedings{LeiEtAl95, author = "T. Leighton and Y. Ma and T. Suel", title = "On Probabilistic Networks for Selection, Merging and Sorting", booktitle = spaa, year = 1995, address = "Santa Barbara", pages = "106--118" } @InProceedings{NegEtAl, author = "A. Negro and N. Santoro and J. Urrutia", title = "On the Packet Complexity of Distributed Selection", pages = "108--115", booktitle = "{CONPAR} ???", year = 1987, publisher = "Springer", annote = "sieht ziemlich straight forward aus." } @InProceedings{Pla89, author = "C. G. Plaxton", title = "On the Network Complexity of Selection", pages = "396--401", booktitle = focs, year = 1989, publisher = "IEEE", annote = "Lower bound fuer selection unter der ich bleibe. Gute einfuehrung des Modells. z.B. verschiedene Schluessel. Knackpunkt ist die unfaehigkeit konzentrierte Datenelemente schnell zu verteilen." } @InProceedings{MilRei85, author = "G. L. Miller and J. H. Reif", title = "Parallel Tree Contraction and its Application", pages = "478--489", booktitle = focs, year = 1985, annote = "Zufallspermutationen" } @InProceedings{Rei85, author = "J. Reif", title = "An optimal parallel algorithm for integer sorting", booktitle = "26th Symposium on Foundations of Computer Science", pages = "490--503", year = 1985 } @InProceedings{Raj98, author = "S. Rajasekaran", title = "A Framework for Simple Sorting Algorithms on Parallel Disk Systems", booktitle = "10th {ACM} Symposium on Parallel Algorithms and Architectures", pages = "88--98", year = 1998 } @Article{RajRei89, author = "S. Rajasekaran and J. H. Reif", title = "Optimal and Sublogarithmic Time Randomized Parallel Sorting Algorithms", journal = "{SIAM} Journal on Computing", year = 1989, volume = 18, number = 3, pages = "594--607", annote = "zufallspermutationen" } @InCollection{Raj92, author = "S. Rajasekaran", booktitle = "Advances in Parallel Algorithms", title = "Randomized Algorithms for Packet Routing on the Mesh", publisher = "Blackwell", year = 1992, editor = "L. Kronsj{\"o} and D. Shumsheruddin", pages = "277--301", annote = "Referenz Chernoff. Interessante Def. von mhw." } @InProceedings{Raj90, author = "S. Rajasekaran", title = "Randomized Parallel Selection", number = 472, series = "LNCS", pages = "215--224", booktitle = "Tenth Conference on Foundations of Software Technology and Theoretical Computer Science", year = 1990, publisher = "Springer", address = "Bangalore", annote = "ziemlich genau mein problem und Algortihmus :-(. Zitiert lower bound _unter_ dem ich bleibe weil Elemente wirklich zufaellig verteilt Er muss den Hypercube extrem ausnutzen um auf die gleiche Zeit zu kommen aber bei mir sind die Routing Probleme einfacher. Er macht nur eine Iteration." } @InCollection{RajSen93, author = "S. Rajasekaran and S. Sen", title = "Random Sampling Techniques and Parallel Algorithm Design", booktitle = "Synthesis of Parallel Algorithms", publisher = "Morgan Kaufmann", year = 1993, editor = "H. Reif", chapter = 9, pages = "411--451", annote = "Schwerpunkt auf sortieren, Einfache Begruendung warum Annahme versch. Werte obda ist." } @Article{Ran94, author = "A. Ranade", title = "Optimal Speedup for Backtrack Search on a Butterfly Network", volume = 27, number = 1, journal = "Mathematical Systems Theory", year = 1994, pages = "85--101", annote = "Optimal skalierbar aber keinerlei Granularitaetskontrolle." } @InProceedings{Reif85, author = "J. H. Reif", title = "An Optimal Parallel Algorithm for Integer Sorting", booktitle = focs, year = 1985, pages = "496--504", annote = "Zufallspermutationen sehr aehnlich wie meine" } @Article{ReiVal87, author = "J. H. Reif and L. G. Valiant", title = "A Logarithmic Time Sort for Linear Size Networks", journal = jacm, year = 1987, volume = 34, number = 1, pages = "60--76", annote = "Referenzpaper fuer Flashsort. Gewohnt unlesbar" } @InCollection{Val90a, author = "L. G. Valiant", title = "General Purpose Parallel Architectures", booktitle = "Handbook of Theoretical Computer Science", publisher = "Elsevier", year = 1990, editor = "J. van Leeuwen", volume = "A: Algorithms and Complexity", pages = "943--971", annote = "Annahme ueber Hash function section 4.3" } @Article{Val94, author = "L. Valiant", title = "A Bridging Model for Parallel Computation", journal = cacm, year = 1994, volume = 33, number = 8, annote = "BSP Referenz in DitEtAl96" } @Book{Neu66, author = "Neumann, J. von", annote = "edited by A. W. Burks", key = "refs-general, CA, automata-theory, complex, automata-selfrepro", title = "Theory of Self-Reproducing Automata", publisher = "University of Illinois Press", address = "Urbana, IL, USA", year = "1966", LCCN = "QA267 .V55", bibdate = "Wed Dec 16 07:25:27 1998", annote = "Von Neumann's work on self-reproducing automata, completed and edited after his death by Arthur Burks. Also includes transcripts of von Neumann's 1949 University of Illinois lectures on the ``Theory and Organization of Complicated Automata''.", acknowledgement = ack-nhfb, } @Article{Hoa61, author = "C. A. R. Hoare", journal = "Communication of the ACM", number = "7", pages = "321", title = "Quicksort", volume = "4", year = "1961", crindex = "Classeur", } @Book{Hoa84, author = "C. A. R. Hoare", title = "Communicating Sequential Processes", publisher = "Prentice-Hall", year = "1984", } @Article{Hoa78, author = "C. A. R. Hoare", title = "Communicating Sequential Processes", journal = "Communications of the ACM", volume = "21", number = "8", pages = "666--677", month = aug, year = "1978", coden = "CACMA2", ISSN = "0001-0782", bibdate = "Tue Mar 25 13:26:09 MST 1997", anote = "See corrigendum \cite{Hoare:1978:CCS}.", abstract = "This paper suggests that input and output are basic primitives of programming and that parallel composition of communicating sequential processes is a fundamental program structuring method. When combined with a development of Dijkstra's guarded command, these concepts are surprisingly versatile. \par Their use is illustrated by sample solutions of a variety of familiar programming exercises.", acknowledgement = ack-nhfb, annote = "This paper is now expanded into an excellent book detailed by Hoare and published by Prentice-Hall. This paper is reproduced in Kuhn and Padua's (1981, IEEE) survey ``Tutorial on Parallel Processing.'' Reproduced in ``Distributed Computing: Concepts and Implementations'' edited by McEntire, O'Reilly and Larson, IEEE, 1984. Somewhat dated.", classcodes = "C6110 (Systems analysis and programming)", classification = "723", corpsource = "Queen's Univ., Belfast, UK", journalabr = "Commun ACM", keywords = "4.22; 4.32 maeder biblio: synchronisation and concurrency in processes; ak; bhibbard grecommended91; classes; computer programming; concurrency; conditional critical regions; coroutines; CR categories: 4.20; CSP; data representations; Dijkstra's guarded command; guarded commands; hcc; input; iterative arrays; k-concurrency; k-csp; k-guarded-commands; monitors; multiple entries; multiple exits; nondeterminacy; output; parallel composition; parallel programming; primitives; procedures; program; program structures; programming; Programming; programming languages; programming primitives; recursion; sequential processes; structured programming; structuring method", treatment = "T Theoretical or Mathematical", } @Article{ReiSen94, author = "J. H. Reif and S. Sen", title = "Randomized Algorithm for Binary Search and Load Balancing on Fixed Connection Networks with Geometric Applications", journal = "{SIAM} Journal on Computing", year = 1994, volume = 23, number = 3, pages = "633--651", annote = "Kurze Einfuehrung von Flash sort. Im grossen und ganzen unlesbar, Lemma fuer whp Ergebnisse bei rekursiven Algorithmen. Benutzt Rajasekarans Def. von Oschlange whp aber nennt es very high likelyhood." } @InProceedings{ReiTat94, author = "J. H. Reif and S. R. Tate", title = "Dynamic Parallel Tree Contraction", pages = "114--121", address = "Cape May, New Jersey", annote = "CRCW, Terminator II Analogie !" } @Article{Rei85, author = "R. Reischuk", title = "Probabilistic Parallel Algorithms for Sorting and Selection", journal = "{SIAM} Journal on Computing", year = 1985, volume = 14, number = 2, pages = "396--409", annote = "abgedrehte Modelle. comparison tree, selection in konst. Zeit mhw!" } @InProceedings{Sav93, author = "S. A. Savari", title = "Average Case Analysis of Five Two-dimensional Bubble Sorting Algorithms", pages = "336--345", booktitle = spaa, year = 1993, address = "Velen" } @Article{Sen90, author = "S. Sen", title = "Finding an approximate median with high probability in constant parallel time", journal = "Information Processing Letters", year = 1990, volume = 34, pages = "77--80" } @Unpublished{Sin98, author = "Alistair Sinclair", title = "Balls and Bins: Load-Balancing", note = "Lecture 15: March 30", annote = "von Volker P. lower bounds for random allocation, kurze Herleitung von balanced random allocation" } @InProceedings{Ste96, author = "V. Stemann", title = "Parallel Balanced Allocation", booktitle = spaa, year = 1996, pages = "261--269", annote = "deja vu (wahrscheinlich AzarEtAl, Adler die er zitiert. Random graph Methoden Durch allocation in mehreren Runden kann in O(log log n) Runden Balance erreicht werden. etc." } @Article{PelUpf89, author = "D. Peleg and E. Upfal", title = "The token distribution problem", journal = "{SIAM} Journal of Computing", year = 1989, volume = 18, pages = "229--243", annote = "Basisreferenz token distribution" } @Article{ABKU00, author = "Y. Azar and A. Z. Broder and A. R. Karlin and Eli Upfal", title = "Balanced Allocations", journal = "SIAM Journal on Computing", volume = "29", number = "1", pages = "180--200", month = feb, year = "2000", coden = "SMJCAT", ISSN = "0097-5397 (print), 1095-7111 (electronic)", bibdate = "Sat Jan 22 13:21:34 MST 2000", url = "http://epubs.siam.org/sam-bin/dbq/article/28849", acknowledgement = ack-nhfb, } @InProceedings{ABKU94, author = "Y. Azar and A. Z. Broder and A. R. Karlin and E. Upfal", title = "Balanced Allocations", pages = "593--602", booktitle = "26th ACM Symposium on the Theory of Computing", year="1994" } @Unpublished{Sai01, author = "J. Saia", title = "Data Migration with Edge Capacities and Machine Speeds", note = "U. Washington", year = 2001 } @InProceedings{HHKSW01, author = "J. Hall and J. Hartline and A. R. Karlin and J. Saia and J. Wilkes", title = "On Algorithms for Efficient Data Migration", booktitle = "12th ACM-SIAM Symposium on Discrete Algorithms", pages = "620--629", year = 2001 } @Article{MorSha94, author = {B.M.E. Moret and H.D. Shapiro}, title = {An Empirical Assessment of Algorithms for Constructing a Minimum Spanning Tree}, journal = {DIMACS Series in Discrete Mathematics and Theoretical Computer Science}, year = {1994}, volume = {15}, pages = {99--117} } @InProceedings{MorSha91, author = "B. M. E. Moret and H. D. Shapiro", title = "An Empirical Analysis of Algorithms for Constructing a Minimum Spanning Tree", pages = "400--411", ISBN = "3-540-54343-0", booktitle = "Workshop Algorithms and Data Structures ({WADS})", month = aug, series = "LNCS", number = "519", publisher = "Springer", year = "1991", } @article{ABW02, AUTHOR = "J. Abello and A. Buchsbaum and J. Westbrook", TITLE = "A Functional Approach to External Graph Algorithms", journal = {Algorithmica}, VOLUME = {32}, number = {3}, PAGES = {437--458}, YEAR = {2002}, } @inproceedings{CGG+95 , author = "Yi-Jen Chiang and Michael T. Goodrich and Edward F. Grove and Roberto Tamassia and Darren E. Vengroff and Jeffey S. Vitter" , title = "External-Memory Graph Algorithms" , pages = "139--149" , booktitle = "Proceedings of the Sixth Annual {ACM}-{SIAM} Symposium on Discrete Algorithms" , year = 1995 , checked = "20020228jv" } @Article{Kin97, author = "V. King", title = "A Simpler Minimum Spanning Tree Verification Algorithm", journal = "Algorithmica", year = 1997, volume = 18, pages = "263--270" } @misc{Mor98, author = {B.M.E. Moret}, title = {Towards a discipline of experimental algorithmics}, year = 1998, note = "Manuscript" } @InProceedings{FatSpi99, author = "P. Fatourou and P. Spirakis", title = "A New Scheduling Algorithm for General Strict Multithreaded Computations", booktitle = "13rd International Symposium on DIStributed Computing (DISC'99)", address = "Bratislava, Slovakia", number = 1693, pages = "297--311", series = "LNCS", year = 1999 } @Article{FatSpi00, volume = 33, number = 3, pages = "173--232", journal = "Theory of Computing Systems Journal", author = "P. Fatourou and P. Spirakis", title = "Efficient Scheduling of Strict Multithreaded Computations", year = 2000 } @InProceedings{FatSpi96, author = "P. Fatourou and P. Spirakis", title = "Scheduling Algorithms for Strict Multithreaded Computations", booktitle = "ISAAC: 7th International Symposium on Algorithms and Computation", number = 1178, pages = "407--416", series = "LNCS", year = 1996 } @InProceedings{Spi86, author = "P. Spirakis", title = "The Diameter of Connected Components of Random Graphs", number = 246, series = "LNCS", pages = "264--275", booktitle = "Workshop on Graph-Theoretic Concepts in Computer Science", year = 1986 } @InProceedings{Upf94, author = "E. Upfal", title = "On the Theory of Interconnection Networks for Parallel Computers", pages = "473--486", booktitle = "Scalable High Performance Computing Conference", year = 1994, address = "Knoxville", annote = "Wormhole routing ist offenes Problem. Zuordnung zu Konferenz nicht ganz sicher. ", address = "Knoxville, TN", publisher = "IEEE, Los Alamitos, CA", } @Article{Sie78, author = "A. F. Siegel", title = "Random Arcs on the Circle", journal = "J. Appl. Probab.", year = 1978, volume = 15, pages = "774--789", note = "studies proportion covered" } @Article{SieHol82, author = "A. F. Siegel and L. Holst", year = "1982", title = "Covering the circle with random arcs of random sizes", journal = "J. Appl. Probab.", volume = "19", pages = "373--381", annote = "geompr; coverage", } @Unpublished{Tre98, author = "R. Treumann", title = "Experiences in The Implementation of a Thread Safe, Threads Based {MPI} for the {IBM RS/6000 SP}", note = "presented at EuroPVM/MPI", year = 1998 } @Article{UpfEtAl96, author = "E. Upfal and S. Felperin and M. Snir", title = "Randomized Routing with Shorter Paths", journal = tpds, year = 1996, volume = 7, number = 4, pages = "356--362", annote = "Will man viele Pakete routen braucht man relativ wenig randomness (O (loglog n) pro zus. Paket)" } @Article{AhaAtt95, author = "E. Aharonson and H. Attiya", title = "Counting networks with arbitrary fan-out", journal = "Distributed Computing", year = 1995, volume = 8, pages = "163--169" } @InProceedings{ShaZem94, author = "N. Shavit and A. Zemach", title = "Diffracting Trees", pages = "167--176", booktitle = spaa, year = 1994, address = "Cape May, New Jersey", annote = "Globales Zaehlen effizienter als Reduktionsbaum" } @Unpublished{ABHMST98, author = "W. Aiello and C. Busch and M. Herlihy and M. Mavranicolas and N. Shavit and D. Touitou", title = "Supporting Increment and Decrement Operations in Balancing Networks", note = "submitted for STACS", year = 1998 } @Article{ShaZem96, author = "N. Shavit and A. Zemach", title = "Diffracting Trees", journal = "IEEE Transactions on Computer Systems", year = 1996, volume = 14, number = 4, pages = "385--428" } @Article{WatWid98, author = "R. Wattenhofer and P. Widmayer", title = "An Inherent Bottleneck in Distributed Counting", journal = "Journal Parallel and Distributed Processing, Special Issue on Parallel and Distributed Data Structures", volume = 49, year = 1998, pages = "135--145" } @InProceedings{ShaTou95, author = "N. Shavit and D. Touitou", title = "Elimination Trees and the Construction of Pools and Stacks", booktitle = spaa, year = 1995, address = "Santa Barbara", pages = "54--63", annote = "Erweiterung des Vorjahres papers ueber diffracting trees. Anwendung fuer pools (i/o Reihenfolge nicht ganrantiert) und stacks. Im Mittel konstante Zugriffszeit!? Sowohl inkrement als auch dekrement moeglich. tokens und anti-tokens koennen sich annihilieren. 'Almost stack'" } @PhdThesis{Sib92, author = "J. Sibeyn", title = "Algorithms for Routing on Meshes", school = "University of Utrecht", year = 1992 } @TechReport{Sib95, author = "J. F. Sibeyn", title = "Sample Sort on Meshes", institution = "{MPI} Informatik", year = 1995, OPTaddress = "Saarbr{\"u}cken", annote = "zweistufig, determinstische Variante, grosse Zahlenmengen. recht gut." } @InProceedings{SibKau97, author = "J. Sibeyn and M. Kaufmann", title = "{BSP}-Like External-Memory Computation", pages = "229-240", booktitle = "3rd Italian Conference on Algorithms and Complexity", year = 1997 } @TechReport{Sib97, author = "J. Sibeyn", title = "From Parallel to External List Ranking", institution = "Max-Planck Institut f{\"u}r Informatik", year = 1997, number = "MPI-I-97-1-021" } @Book{SuaBir89, author = "R. Suaya and G. Birtwistle (eds.)", title = "{VLSI} and Parallel Compuation", publisher = "Morgan Kaufmann", year = 1989, annote = "Mit Artikeln von E.W. Mayr, W. Dally, Dally sagt warum meshes u.U. besser als HC, Johnsson zeigt embedding HC mesh" } @Article{Dal93, author = "W. J. Dally", title = "A Universal Parallel Comptuer Architecture", journal = "New Generation Computing", year = 1993, number = 11, pages = "227--249", annote = "Motivation fuer J-Machine?" } @InProceedings{FelEtAl92, author = "S. Felpering and P. Raghavan and E. Upfal", title = "A Theory of Wormhole Routing in Parallel Computers", pages = "563--572", booktitle = focs, year = 1992, publisher = "IEEE", annote = "Beispiel fuer meine schwaechere Def. von whp. Auf Butterfly geht routing in O(L min(L, N)log N) sei L Nachrichtenlaenge, N PE-Zahl. Auf mesh: O(sqrt(N)L\log N + N/log N. Also alles ziemilich schlecht. Unterschied zu einfachen Algorithmen: Zufaelliges Warten am Anfang. Simulationen zeigen, dass kurzes Warten gut sein kann. Aber der theoretesche Algorithmus wartet l a n g e damit die W klein wird, dass Nachrichten sich blockieren. Besondere Schwierigkeit: Ketten von Nachrichten blockieren sich indirekt." } @Proceedings{ParResRam94, title = "Parallel Processing of Discrete Opitmization Problems", year = 1994, editor = "P. M. Pardalos and G. C. Resende and K. G. Ramakrishnan", number = 22, publisher = "{DIMACS}" } @Article{FelEtAl96, author = "S. Felpering and P. Raghavan and E. Upfal", title = "A Theory of Wormhole Routing in Parallel Computers", journal = "IEEE Transactions on Computers", year = 1996, volume = 48, number = 6, pages = "704--713", annote = "siehe auch obiges FOCS paper" } @Article{Wes94, author = "J. Westbrook", title = "Randomized Algorithms for Multiprocessor Page Migration", journal = "{SIAM} Journal on Computing", year = 1994, volume = 23, number = 5, pages = "951--965", annote = "eine Seite pro PE. Fuer jede Seite und jede PE einen Zaehler, der zufaellig initialisiert wird. Bei Zugriff dekremtierung. =0 ? => migrieren und ruecksetzen. optimiere die setz/ruechsetzverteilung. Problem: worst case (competitive) wird optimiert. Aber der ist wahrscheinlich ohnehin so schlecht dass es nicht hilft. Def. oblivious und adaptive adversary. Markov ketten." } @Article{ZhaKor94, author = "W. Zhang and R. E. Korf", title = "Parallel Heap Operations on an EREW PRAM", journal = jpdc, year = 1994, volume = 20, pages = "248--255", annote = "Algorithmus der auf schnelles Entfernen eines Elements getunt ist. Zeit O((log n)/p + log p) bringt also nur bei exponentiellen queue Groessen einen Vorteil." } %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % sequentielle Suche @Article{CarPin89, author = "J. Carlier and E. Pinson", title = "An Algorithm for Solving the Job-Shop Problem", journal = "Management Science", year = 1989, volume = 35, number = 2, pages = "164--176", annote = "OR-Kram" } @Article{DilNel94, author = "J. F. Dillenburg and P. C. Nelson", title = "Perimeter Search", journal = aint, year = 1994, volume = 65, pages = "165--178", annote = "Biderektionale bei der durch Bewertung def. Umkreis um Ziel expandiert wird. Problem: Heuristik zu allen Knoten im Perimeter wird gebraucht. -> 15-Puzzle" } @Book{HorSah78, author = "E. Horowitz and S. Sahni", title = "Fundamentals of Computer Algorithms", publisher = "Computer Science Press", year = 1978 } @Article{Kor85, author = "R. E. Korf", title = "Depth-First Iterative-Deepening: An Optimal Admissible Tree Search", journal = aint, year = 1985, volume = 27, pages = "97--109", annote = "Daten fuer 15-Puzzle, IDA* Ursprungspaper" } @Article{Kor93, author = "R. E. Korf", title = "Linear-space best-first search", journal = aint, year = 1993, volume = 62, pages = "41--78", annote = "Haupteigenschaft: Neue Knoten werden in best first order expandiert. Vergleich mit verwandten Verfahren, 15 Puzzle. Rein rekursiver Tiefensuchalgorithmus der Bound so geschickt waehlt das nie voreilig entschieden wird. Wird nichtrivial dadurch das in bekanntem Gelaende (das gerade reexpandiert wird etwas anders vorgegangen wird. DFB\&B generiert nur 10\% mehr Knoten als best first fuer euklidische TSP mit Spannbaumheuristik! fuer 15 Puzzle ungefaehr gleiche Leistung v. IDA* und RBFS" } @Article{Par95, author = "I. Parberry", title = "A real-time algorithm for the $(n^2 - 1)$-puzzle", journal = "Information Processing Letters", year = 1995, volume = 56, pages = "23--28" } @Article{RatWar90, author = "D. Ratner and M. Warmuth", title = "Finding a Shortest Solution to the $N\times N$ Extension of the 15-Puzzle is Intractable", journal = "Journal of Symbolic Computation", year = 1990, volume = 10, pages = "111-137" } @Article{NiePla89, author = "X. Nie and D. A. Plaisted", title = "Refinements to Depth-First Iterative Deepening Search in Automatic Theorem Proving", journal = aint, year = 1989, volume = 41, pages = "223--235", annote = "abstrus" } @InCollection{Hel88, author = "P. Helman", title = "An Algebra for Search Problems and their Solutions", booktitle = "Search in Artificial Intelligence", publisher = "Springer", year = 1988, editor = "V. Kumar and L. N. Kanal", pages = "28--90", annote = "Hammerhart, Betonung auf Dominanzrelationen. Behaupten ein gutes Modell fuer Komplixeitaetsuntersuchungen gefunden zu haben." } @InProceedings{Hog94, author = "T. Hogg", title = "Statistical Mechanics of Combinatorial Search", booktitle = "Physics and Computation", year = 1994, pages = "196--202", annote = "Modell fuer Graph coloring" } @InCollection{BagSen88, author = "A. Bagchi and A. K. Sen", title = "Average-Case Analysis of Heuristic Search in Tree-like Networks", booktitle = "Search in Artificial Intelligence", publisher = "Springer", year = 1988, editor = "V. Kumar and L. N. Kanal", pages = "28--90", annote = "Aehlich zu Pearls Betrachtungen. Unterschied: mehr als ein goal-node" } %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Kumars Stuff @TechReport{ArvEtAl90a, author = "S. Arvindam and V. Kumar and V. N. Rao and V. Singh", title = "Automatic Test Pattern Generator on Parallel Processors", institution = "University of Minnesota", year = 1990, number = "TR 90-20", annote = "Short version in Proc. Intl. Conference on Knowledge-Based Computer Systems, December 1989. Hier wird das falsche Ergebnis fuer Random Polling ausfuehrlich benutzt. Speedup Anomalien" } @InProceedings{ArvEtAl90b, author = "S. Arvindam and V. Kumar and V. N. Rao", title = "Efficient Parallel Algorithms for Search Problems: Applications in {VLSI} {CAD}", booktitle = "3rd Symposium on Massively Parallel Computation", year = 1990, annote = "VLSI floorplan optimization, tautology verification, tiefensuche, random polling? kurzer ueberblick", address = "College Park, MD, 8--10 October", publisher = "NASA/IEEE, Los Alamitos, CA", } @InProceedings{EveEtAl90, author = "M. Evett and J. Hendler and A. Mahanti and D. Nau", title = "{PRA*}: A memory-limited heuristic search procedure for the {C}onnection {M}achine", pages = "145--149", booktitle = "3rd Symposium On the Frontiers Of Massively Parallel Computation", year = 1990, address = "College Park, Maryland", annote = "Bei Speichermangel werden die schlechtesten Knoten durch ihre Vorgaenger ersetzt. Ansonsten ist das Karp-Zhangs local best first Algorithmus!" } @Article{NauEtAl84, author = "D. S. Nau and V. Kumar and L. Kanal", title = "General Branch and Bound, and Its Relation to {A*} and {AO*}", journal = aint, year = 1984, volume = 23, pages = "29--58", annote = "Gaehn" } @Article{KumKan84, author = "V. Kumar and L. N. Kanal", title = "Parallel Branch-and-Bound Formulations for {AND}/{OR} Tree Search", journal = pami, year = 1984, volume = 6, number = 6, pages = "768--778", annote = "SSS* im Branch and Bound Gewand. Maessig erfolgreiche Parallelisierung" } @InCollection{KumKan88, author = "V. Kumar and L. N. Kanal", title = "The CDP: A Unifying Formulation for Heuristic Search, Dynamic Programming and Branch-and-Bound", booktitle = "Search in Artificial Intelligence", publisher = "Springer", year = 1988, editor = "V. Kumar and L. N. Kanal", pages = "1--27", annote = "Info Bib: F Sea, Vereinheitlichung verschiedener Suchformalismen durch was Grammatikmaessiges. z.B. dyn prog. und BuB" } @InCollection{SchKarKum00, author = "K. Schloegel and G. Karypis and V. Kumar", title = "Graph Partitioning for High Performance Scientific Simulations", booktitle = "CRPC Parallel Computing Handbook", publisher = "Morgan Kaufmann", year = 2000, editor = "J. Dongarra et al.", note = "to appear, {\protect\url{http://www-users.cs.umn.edu/~karypis/publications/partitioning.html}}" } @Book{KumEtAl94, author = "V. Kumar and A. Grama and A. Gupta and G. Karypis", title = "Introduction to Parallel Computing. Design and Analysis of Algorithms", publisher = "Benjamin/Cummings", year = 1994, annote = "S. 316: Er behauptet immer alpha splitting zu koennen." } @Book{KumEtAl94vorl, author = "V. Kumar and A. Grama and A. Gupta and G. Karypis", title = "Introduction to Parallel Computing. Design and Analysis of Algorithms", publisher = "Benjamin/Cummings", year = 1994, note = "einfaches, praxisnahes Buch" } @TechReport{KarKum92, author = "G. Karypis and V. Kumar", title = "Unstructured Tree Search on {SIMD} Parallel Computers", institution = "University of Minnesota", year = 1992, month = "April", annote = "Triggering schemes sind schon drin. Ausfuerhlicher als Zeitschriftenversion. Berechnung eines optimalen statischen Triggers. " } @Article{KarKum94, author = "G. Karypis and V. Kumar", title = "Unstructured Tree Search on {SIMD} Parallel Computers", journal = tpds, year = 1994, volume = 5, number = 10, pages = "1057--1072", annote = "Wie Powley und Co. aber genauere Untersuchung von Triggering Mechanismen. Analyse etwas krank: Sie nehmen an, routing auf CM-2 log^2 n braucht???" } @InProceedings{GupEtAl96, author = "A. Gupta and G. Karypis and V. Kumar", title = "Scalable Parallel Algorithms for Sparse Linear Systems", booktitle = "??", year = 1996, annote = "bis 1024 PEs einer T3D" } @TechReport{KumAna91, author = "V. Kumar and G. Y. Ananth", title = "Scalable Load Balancing Techniques for Parallel Computers", institution = "University of Minnesota", year = 1991, number = "TR 91-55", annote = "Isoeffizienzanalyse von: Round Robin (global/lokal) nearest neighbor, random polling, zentral, hierearchisch. Er benutzt allgemeines Framework das speziell auf global round robin zugeschnitten ist und z.B. fuer random polling nur eine Abschaetzung liefert, Randomized Allocation. Behandlung von variabler Nachrichtengroesse. Untere Schranke fuer Load Balancing Isoeffisienz von PD(P) ist zu optimistisch." } @InProceedings{KumNob91, author = "K. Kimura and N. Ichiyoshi", title = "Probabilistic Analysis of the efficiency of the dynamic load distribution", booktitle = "6th Distributed Memory Computing Conference", year = 1991, address = "Portland", annote = "Multi-Level Server based Scheduling. Benutzen probabilistisches Modell. Teilproblemgroessen sind (unabhaengige?) Zufallsvariablen. Fuer dieses Modell duerfte die Analyse OK sein." } % was Kum90 @InCollection{KumRao90, author = "V. Kumar and V. N. Rao", title = "Scalable parallel formulations of depth-first search", booktitle = "Parallel Algorithms for Machine Intelligence and Vision ", publisher = "Springer", year = 1990, editor = "V. Kumar", annote = "Weitere Sachen ueber Isoeffizienz. Aber ziemlich alte Sachen" } @TechReport{KumGup92, author = "V. Kumar and A. Gupta", title = "Analyzing Scalability of Parallel Algorithms and Architectures", institution = "University of Minnesota", year = 1992, number = "TR 91-18 revised", month = "January", annote = "Diskussiong verschiedener Skalierbarkeitsmasse" } @Article{RaoKum88, author = "V. N. Rao and V. Kumar", title = "Concurrent Access of Priority Queues", journal = ietc, year = 1988, volume = 37, number = 12, pages = "1657--1665", annote = "pipelining von log P updates. Funktioniert nur auf shared memory." } @Article{RaoKum87a, author = "V. N. Rao and V. Kumar", title = "Parallel Depth First Search. {Part} {I}", journal = ijpp, year = 1987, volume = 16, number = 6, pages = "470--499", annote = "Erstes Beispiel fuer grossen Speedup (128 PEs) 15 Puzzle" } @Article{RaoKum87b, author = "V. N. Rao and V. Kumar", title = "Parallel Depth First Search. {Part} {II}", journal = ijpp, year = 1987, volume = 16, number = 6, pages = "501--519", annote = "Analyse NN DLB fuer Ring und Hypercube" } @Article{RaoKum87ab, author = "V. N. Rao and V. Kumar", title = "Parallel Depth First Search.", journal = ijpp, year = 1987, volume = 16, number = 6, pages = "470--519", annote = "Analyse NN DLB fuer Ring und Hypercube" } @Article{RaoKum93, author = "V. N. Rao and V. Kumar", title = "On the Efficiency of Parallel Backtracking", journal = tpds, year = 1993, volume = 4, number = 4, pages = "427--437", month = "April", annote = "Verschiedene Beweise, die konsistente amortisierte Effizienz > 1 beweisen. Zweifelhaft: obskures Modell fuer ungleichmaessige Loesungsverteilung. Wer sagt, dass die nicht mit zunehmender Problemgroesse kleiner wird." } @Article{SinEtAl91a, author = "V. Singh and V. Kumar and G. Agha and C. Tomlinson", title = "Efficient Algorithms for Parallel Sorting on Mesh Multicomputers", journal = ijpp, year = 1991, volume = 20, number = 2, pages = "95--131", annote = "Langversion des ICPP papers" } @InProceedings{SinEtAl91, author = "V. Singh and V. Kumar and G. Agha and C. Tomlinson", title = "Efficient Algorithms for Parallel Sorting on Mesh Multicomputers", pages = "92--101", booktitle = "5th International Parallel Processing Symposium", year = 1991, publisher = "IEEE", annote = "erster Teil ziemlich trivial, ein bekannter Algorithmus wird naiv verallgemeinert und dann geilt er sich daran auf, das sein Algorithmus besser ist. Er benutzt parallels Quicksort mit zeilenweiser Knotennumerierung. QSP-2 ist asympt. optimal aber im strengen Sinne kein Sortieralg. weil die PE Numerierung dynamisch bestimmt wird. Erwaehnt Moeglichkeit Partition boundaries innerhalb eines PE zu erlauben. Macht aber falsche Abschaetzung des Kommunikationsaufwands. Sie haben massive Probleme mit Lastimbalance" } %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Paderborn @TechReport{Bur94, author = "M. Buro", title = "The 1st International Paderborn Computer-Othello Tournament", institution = "Universit{\"a}t Paderborn", year = 1994, number = 141, annote = "Verweise auf einige interessante Othello papers" } @InCollection{MonEtAl90, author = "B. Monien and R. Feldmann and P. Mysliwietz and O. Vornberger", title = "Parrallel game tree search by dynamic tree decomposition", editor = "Vipin Kumar and P. S. Gopalakrishnan and Laveen Kanal", booktitle = "Parallel Algorithms for Machine Intelligence and Vision", publisher = "Springer-Verlag", address = "New York", year = "1990", } @InProceedings{FunEtAl92, author = "R. Funke and R. L{\"u}ling and B. Monien and F. L{\"u}cking and H. Blanke-Bohne", title = "An optimized reconfigurable architecture for Transputer networks", volume = 1, year = 1992, pages = "237--245", booktitle = "25th Hawaii Int. Conference on System Sciences", address = "Hawaii", annote = "Super Cluster" } @Article{BroSch00, author = "M. Brockington and J. Schaeffer", title = "{APHID}: Asynchronous Parallel Game-Tree Search", journal = "Journal of Parallel and Distributed Processing", year = 2000, pages = "247--273", annote = "asynchron im Sinne von wenigen Datenabhaengigkeiten. integriert mit starken Programmen, " } @Unpublished{Pla01, author = "A. Plagne", title = "On threshold properties of k-SAT. An additive viewpoint", note = " ", year = 2001, annote = "stacs01?" } @Unpublished{LorMon01, author = "U. Lorenz and B. Monien", title = "The Secret of Selective Game Tree Search, when Using Random-Error Evaluations", note = " ", year = 2001, annote = "stacs01?" } @InProceedings{FelEtAl91s, author = "R. Feldmann and P. Mysliwietz and B. Monien", title = "Distributed Game Tree Search on a Massively Parallel System", booktitle = "Data structures and efficient algorithms: Final report on the {DFG} special joint initiative", pages = "270--288", series = "LNCS", number = 594, year = 1991, annote = "noch besorgen" } @InProceedings{FelEtAl91, author = "R. Feldmann and P. Mysliwietz and B. Monien", title = "Distributed Game Tree Search on a Massively Parallel System", booktitle = "Data structures and efficient algorithms: Final report on the {DFG} special joint initiative", publisher = "Springer-Verlag", editor = "Th. Ottmann and B. Monien", pages = "270--288", series = "LNCS", number = 594, month = Sep, year = "1991", annote = "noch besorgen" } @Article{BenOtt79, author = "J. L. Bentley and T. A. Ottmann", title = "Algorithms for reporting and counting geometric intersections", pages = "643--647", journal = "IEEE Transactions on Computers", year = "1979", keywords = "algorithmic aspects, intersections, mathematical aspects, computational geometry, surface graphics, intersection", } @PhdThesis{Fel93, author = "R. Feldmann", title = "Game Tree Search on Massively Parallel Systems", school = "Universit{\"a}t Paderborn", type = "Dissertation", year = 1993, month = "August" } @InProceedings{FelEtAl94, author = "R. Feldmann and P. Mysliwietz and B. Monien", title = "Studying Overheads in Massively Parallel Min/Max-Tree Evaluation", pages = "94--103", booktitle = spaa, year = 1994, annote = "[12] ist Referenz fuer Othello, Kurze Skizze von Hsus Ansatz, Karp Zhang haben theor. Ergebnis verbessert.", address = "Cape May, NJ, 27--29 June", publisher = "ACM, New York", } @InProceedings{LueEtAl91, author = "R. L{\"u}ling and B. Monien and F. Ramme", booktitle = "3rd IEEE Symposium on Parallel and Distributed Processing", organization = "IEEE", title = "Load Balancing in Large Networks: {A} Comparative Case Study", year = "1991", annote = "Netter Rueckblich auf aeltere Arbeiten. Benutzung eines ausfuehrlichen Simulationsmodells zum Vergleich von Lastverteilungsalgorithmen. Best first Suche. Klassifikation von DLB nach lokal/global Entscheidungen, lokal/global Lastbewegung, sender/empfaenger- initiiert. Hinweis auf 2 mir unbekannte Algorithmen (bidding, drafting) aber die sind ziemlich schlecht. Deutlich verbesserte version des Gradienten modells: Es wird explizit gesagt, dass mit alten Werten gearbeitet wird; symmetrische Behandlung von High/Low belasteten PEs. Weitere Variante: Pakete werden von Medium PEs direkt entsprechend dem Gradienten weitergeleitet. Gutes Beispiel warum inflexible Routing Hardware ein Problem sein koennte. Interessanter Hinweis dass auch 324 PEs noch nicht reichen um ueber DeBruijn und Co vernuenftige Aussagen zu machen; Deshalb Torus und sogar Ring." } @InProceedings{LueMon92, author = "R. L{\"u}ling and B. Monien", booktitle = "Int. Parallel Processing Symposium (IPPS)", key = "new", title = "Load Balancing for Distributed Branch \& Bound Algorithms", year = "1992", annote = "best first mit neighborhood averaging. Flusskontrolle: erst balancieren wenn last sich um bestimmten Faktor geaendert hat. Zusaetzlich Flussbeschraenkung waere aber leichter durch Prozesspriotitaeten zu modellieren. Zwei Literaturhinweise. Z.B. am besten 2. besten Knoten abgeben. Interessante Diskussion wie die Last eines PE unter beruechsichtigung der Qualitaet gemessen werden kann. Benutzen sowas wie direkte Initialisierung (fuer Vertex Cover)" } @InCollection{MonEtAl96, author = "B. Monien and R. Dickmann and R. Feldmann and R. Klasing and R. L{\"u}ling and Knut Menzel and R. R{\"o}mke and U. Schroeder", title = "Efficient Use of Parallel \& Distributed Systems: From Theory to Practice ", booktitle = "Computer Science Today", publisher = "Springer", year = 1996, number = 1000, series = "LNCS" } @Book{Rei89, author = "Alexander Reinefeld", title = "Spielbaum-{Suchverfahren}", publisher = "Springer-Verlag", address = "New York, NY", series = "Informatik-Fachberichte ", number = "200", year = "1989", avcode = "available -- ETHICS", } @InCollection{LueEtAl96, author = "R. L{\"u}ling and B. Monien and A. Reinefeld and S. Tsch{\"o}ke", title = "Mapping Tree-Structured Conbinatorial Optimization Problems onto Parallel Computers", booktitle = "Solving Combinatorial Optimization Problems in Parallel", publisher = "Springer", year = 1996, editor = "A. Ferreira and P. M. Pardalos", pages = "127--144", annote = "Zusammenfassung von altem Kram. Zahlen zu Vertex Cover auf 1024 PEs" } @InCollection{Tsc94, author = "S. Tsch{\"o}ke", title = "A Portable Parallel Branch-and-Bound Library (PPBB-Lib)", booktitle = "{PC$^2$} User Report", publisher = "{PC$^2$}", year = 1994, editor = "B. Bauer", number = "TR-009-94", month = "Jun.", pages = "31--33" } @InCollection{CorFer96, author = "R. Corr{\^e}a and A. Ferreira", title = "Parallel Best-First Branch-and-Bound in Discrete Optimization: a Framework", booktitle = "Solving Combinatorial Optimization Problems in Parallel", publisher = "Springer", year = 1996, editor = "A. Ferreira and P. M. Pardalos", pages = "171--200", annote = "Uebersicht ueber implementierte Anwendungen, Lastverteilungsstrategien. Offenenes Problem: real world Anwendungen." } @InCollection{BenEtAl96, author = "M. Bena{\"\i}ouche and V. Cung and S. Dowaji and Le Cun, B. and T. Mautor and C. Roucairol", title = "Building a Parallel Branch and Bound Library", booktitle = "Solving Combinatorial Optimization Problems in Parallel", publisher = "Springer", year = 1996, editor = "A. Ferreira and P. M. Pardalos", pages = "201--231", annote = "Behaupted D-Heap sei ineffizient" } @InCollection{BruEtAl96, author = "de Bruin, A. and G. A. P. Kindervater and H. W. J. M. Trienekens", title = "Towards an Abstract Parallel Branch and Bound Machine", booktitle = "Solving Combinatorial Optimization Problems in Parallel", publisher = "Springer", year = 1996, editor = "A. Ferreira and P. M. Pardalos", pages = "145--170", annote = "Hauptsaechlich best first. Schichtenmodell kommt mir bekannt vor. Uebersicht ueber abstrakte Modelle, bisherige Bibliotheken. Erwaehnen explizit, das existierende Bibliotheken die Zielarchitektur festhalten." } @InCollection{CunRou95, author = "Le Cun, B. and C. Roucairol", title = "Concurrent Data Structures for Tree Structured Search Algorithms", booktitle = "Parallel Algorithms for Irregular Problems: State of the Art", publisher = "Kluwer", year = 1995, editor = "A. Ferreira and J. D. P. Rolim", chapter = 7, pages = "135--155", annote = "eigentlich proceedings Irregular 94, Ueberblick ueber PPQ Verfahren. Verwaltung von open und closed set gleichzeitig durch treap in A*" } @InCollection{CorFer95, author = "R. Corr{\^e}a and A. Ferreira", title = "A distributed implementation of asynchronous parallel branch and bound", booktitle = "Parallel Algorithms for Irregular Problems: State of the Art", publisher = "Kluwer", year = 1995, editor = "A. Ferreira and J. D. P. Rolim", chapter = 8, pages = "157--176", annote = "eigentlich Proceedings Irregular 94. Wenig spannden. Best first fuer Rucksack Problem" } @InCollection{Sod95, author = "A. Sodan", title = "Atredia: A mapping environment for dynamic tree-structured problems", booktitle = "Parallel Algorithms for Irregular Problems: State of the Art", publisher = "Kluwer", year = 1995, editor = "A. Ferreira and J. D. P. Rolim", chapter = 14, pages = "269--296", annote = "Lisp, GMD-FIRST Berlin, elaborates Verfahren fuer Teilproblemgroessenvorraussage. Einige Argumente gegen Tree splitting - kann man widerlegen" } @InProceedings{MonEtAl92, author = "B. Monien and R. L{\"u}ling and F. Langhammer", title = "A realizable efficient parallel architecture ", number = 678, series = "LNCS", pages = "93--109", booktitle = "First Heinz Nixdorf Symposium", year = 1992, annote = "clos" } @TechReport{LueMon94, author = "R. L{\"u}ling and B. Monien", title = "A Dynamic Load Balancing Algorithm with Provable Good Performance", institution = "Universit{\"a}t Paderborn", year = 1994, annote = "Mischung aus Random Polling und Random Distribution. Trigger: lokale Aenderung um bestimmten Faktor. Gute Literaturuebersicht. Zunaechst wird Ew_i/Ew_j wird bestimmt-> konstanter Faktor. Zusaetzlich wird die Variationsdichte bestimmt (stdAbw/E). Frage wie uebersetzt sich das in Maximum? Interessant: Anwendung des Banachschen Fixpunktsatzes. Problem damit: das ist nur eine Grensbetrachtung und es ist nicht ganz klar wie schnell sich dieses Gleichgewicht einstellt. Ist es mal hergestellt wird es aber wohl bestehen bleiben. " } @Book{AaKo89, author = "E. H. L. Aarts and J. H. M Korst", address = "Chichester, U.K.", publisher = "John Wiley \& Sons", title = "Simulated Annealing and Boltzmann Machines", year = "1989", annote = "Book providing an overview of simulated annealing techniques and issues.", } @TechReport{AKV00b, author = {Aerts,J. and Korst,J. and Verhaegh,W.}, title = {Complexity of retrieval problems}, institution = {Philips Research Laboratories}, year = {2000}, number = {NL-MS-20.899}, place = {Eindhoven, The Netherlands} } @InProceedings{AKV00, author = "J. Aerts and J. Korst and W. Verhaegh", title = "Load balancing in multimedia servers", booktitle = "Workshop on Project Management and Scheduling PMS", pages = "25--28", year = 2000 } @Article{Tov84, author = "C. A. Tovey", title = "A simplified {NP}-complete satisfiability problem", journal = "Discrete Applied Mathematics", year = 1984, volume = 8, pages = "85--89" } @Article{AKE00a, author = "J. Aerts and J. Korst and S. Egner", title = "Random duplicate storage for load balancing in multimedia servers", journal = "Information Processing Letters", volume = "76", number = "1--2", year = 2000, pages = "51--59", } @TechReport{DieEtAl93, author = "R. Diekmann and R. L{\"u}eling and J. Simon", title = "Problem Independent Distributed Simulated Annealing and its Applications", institution = "Universit{\"a}t Paderborn", year = 1993, note = "Auch auf SPDP 92", annote = "Ebenen der Parallelitaet: Bewertung eines Kandidaten -> Anwendungsspezifisch; Generierung u. Bewertung von Muatanten -> Geringe Parallelitaet zu Beginn; Betrachtung paralleler Entwicklungsfaeden: Konvergenzprobleme oder viel redundante Arbeit. Synthese: Zu Beginn viele Parallel Faeden gegen Schluss weniger werdend. Speedup 70 bei 120 PEs 320 hatte wohl keinen Sinn? Anwendung fuer TSP und SuperCluster Konfigurierung" } @Article{BerDas00, author = "P. Berman and B. DasGupta", title = "Multi-phase Algorithms for Throughput Maximization for Real-Time Scheduling", journal = "Journal of Combinatorial Optimization", year = 2000, volume = 4, number = 3, pages = "307--323", annote = "use van Emde Boas trees" } @InCollection{KroVor90, author = "B. Kr{\"o}ger and O. Vornberger", title = "Enumerative vs. Genetic Optimization. Two Parallel Algorithms for the Bin Packing Problem", booktitle = "Data Structures and Efficient Algorithms: Final Report on the DFG Special Joint Initiative", publisher = "Springer", year = 1990, editor = "B. Monien and T. Ottmann", number = 594, series = "LNCS", annote = "2D Bin Packing, 32 T800" } @InProceedings{MonEtAl94, author = "B. Monien and R. Diekmann and R. L{\"u}ling", title = "Communication Throughput of Interconnection Networks", series = "LNCS", booktitle = "MFCS", year = 1994, publisher = "Springer", annote = "Referenz auf Wormhole Analyse. Betrachten anderes Mass als Bisektionsbreite" } @InProceedings{Rei93, author = "A. Reinefeld", title = "Complete Solution of the Eight-Puzzle and the Benefit fo Node Ordering in {IDA*}", pages = "248--253", booktitle = "13th International Conference on Artificial Intelligence", year = 1993, address = "Chambery, France", annote = "Daten darueber was best first sowie Tabellen bringen" } @Unpublished{FraGarLuq99, author = "D. Franco and I. Garc{\'{e}}s and E. Luque", title = "An Analytical Model of the Interconnection Network Latency Behavior", note = " ", annote = "Europar'99 eingereicht" } @Unpublished{FraGarLuq99, author = "D. Franco and I. Garc{\'{e}}s and E. Luque", title = "A New Method to Avoid Hot Spots in Interconnection Networks for Parallel Computers", note = " ", annote = "Europar'99 eingereich" } @InProceedings{Rei94, author = "A. Reinefeld", title = "Scalability of Massively Parallel Depth-First Search", booktitle = "Parallel Processing of Discrete Optimization Problems", pages = "305--322", year = 1995, number = 22, series = "DIMACS Series in Discrete Mathem. and Theor. Comp. Sc.", publisher = "AMS-Press, New York" } @InProceedings{ReiSch94a, author = "A. Reinefeld and V. Schnecke", title = "Work-Load Balancing in Highly Parallel Depth-First Search", pages = "773--780", booktitle = "Scalable High Performance Computing Conference", year = 1994, address = "Knoxville", annote = "PDFS, Initialisierung durch replizierte Breitensuche, so erzeugt Pakete gelten als unteilbar. DLB Nachbarschafts Polling mit weiterreichen. Anwendungen 15-Puzzle und floorplan optimization." } @InProceedings{ReiSch94b, author = "A. Reinefeld and V. Schnecke", title = "{AIDA*} --- Asynchronous Parallel {IDA*}", booktitle = "10th Canadian Conference on Artificial Intelligence", year = 1994, address = "Banff", annote = "Praktisch, detaillierte Daten ueber einzelne Probleme" } @InProceedings{Rei94c, author = "A. Reinefeld", title = "Effective Parallel Backtracking Methods for Operations Research Applications.", booktitle = "International Conference Massively Parallel Processing Applications and Development", year = 1994, pages = "117--124", address = "Delft", annote = "das uebliche" } @TechReport{TscEtAl94, author = "S. Tsch{\"o}ke and M. R{\"a}cke and R. L{\"u}ling and B. Monien", title = "Solving the Traveling Salesman Problem with a Parallel Branch-and-Bound Algorithm on a 1024 Processor Network", institution = "Universit{\"a}t Paderborn", year = 1994, annote = "LB mit Nachbarschaftskomm. a la Mc Keown + Co. aber niemanden zitiert. Guter Speedup fuer Probleme mit 200-800 s Tpar und extrem aufwendiger Knotenauswertungsfunktion. Fuktioniert bis 318 Staedte." } @InProceedings{TscEtAl94b, author = "S. Tsch{\"o}ke and R. L{\"u}ling and B. Monien", title = "{E}ine {T}oolbox {z}ur {a}utomatischen {P}arallelisierung {b}eliebiger {B}ranch \& {B}ound {A}pplikationen", pages = "149--154", booktitle = "Transputer Anwender Treffen", year = 1994, publisher = "IOS Press" } @InProceedings{TscHol95, author = "S. Tsch{\"o}ke and N. Holth{\"o}fer", title = "A New Parallel Approach to the Constrained Two-Dimensional Cutting Stock Problem", pages = "285--299", booktitle = "Workshop on Algorithms for Irregularly Structured Problems", year = 1995, publisher = "Springer", address = "Lyon" } @InProceedings{Vor87, author = "O. Vornberger", title = "Implementing Branch-and-Bound in a Ring of Processors", pages = "157--164", booktitle = "{CONPAR}", year = 1987, publisher = "Springer", annote = "Hier hat Reinefeld sein Initialisierung durch Breitensuche her?" } @Article{Vor88, title = "Load Balancing in a Network of Transputers", journal = "2nd International Workshop on Distributed Algorithms", address = "Amsterdam", pages = "116--126", author = "O. Vornberger", year = 1988, month = jun, annote = "Beschreibt Vertex Cover" } @Book{BKOS97, author = "de Berg, M. van Kreveld, M. and Overmars, M. and O. Schwarzkopf", title = "Computational Geometry Algorithms and Applications", publisher = "Springer-Verlag", EDITION = {2., rev. ed.}, address = "Berlin Heidelberg", year = "2000", ISBN = "3-540-61270-x", descriptor = "Geometrische Algorithmen", } %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Karlsruhe @TechReport{KucEtAl93b, author = "N. Kuck and M. Middendorf and H. Schmeck", title = "Generic Branch-and-Bound on a Network of Transputers", institution = "Universit{\"a}t Karlsruhe, AIFB", year = 1993, number = 283, annote = "Wie Konferenzpaper" } @InProceedings{Gut04, author = "R. Gutman", title = "Reach-based Routing: A New Approach to Shortest Path Algorithms Optimized for Road Networks", booktitle = "Alenex", year = 2004, annote = "patented" } @TechReport{GolHar03, author = "A. V. Goldberg and C. Harrelson", title = "Computing the Shortest Path: $A^*$ Meets Graph Theory", institution = "Microsoft Research", year = 2004, number = "MSR-TR-2004-24", annote = "date is March 19, 2003. concept of landmarks for computing lower bounds" } @InProceedings{GolMor99, author = "A. Goldberg and B. Moret", title = "Combinatorial Algorithms Test Sets (CATS)", booktitle = "10th {ACM}-{SIAM} Symposium on Discrete Algorithms", pages = "", year = 1999 } @Article{OOW99, author = "O'Neil and O'Neil and Weikum", title = "An Optimality Proof of the {LRU}-{K} Page Replacement Algorithm", journal = "JACM: Journal of the ACM", volume = "46", year = "1999", } @InCollection{Ira98, author = "S. Irani", title = "Competetive Analysis of Paging", booktitle = "Online Algorithms --- The State of the Art", pages = "52--73", publisher = "Springer", year = 1998, volume = 1442, series = "LNCS" } @article{NaoRei99, author = "M. Naor and O. Reingold", title = "On the Construction of Pseudorandom Permutations: {Luby-Rackoff} Revisited", journal = "Journal of Cryptology: the journal of the International Association for Cryptologic Research", volume = "12", number = "1", pages = "29--66", year = "1999", url = "citeseer.nj.nec.com/article/naor97construction.html" } @Article{Fei98, author = "U. Feige", title = "A threshold of $\ln n$ for approximating set cover", journal = "Journal of the ACM", volume = "45", number = "4", pages = "634--652", month = jul, year = "1998", coden = "JACOAH", ISSN = "0004-5411", bibdate = "Wed Dec 16 07:11:23 MST 1998", url = "http://www.acm.org:80/pubs/citations/journals/jacm/1998-45-4/p634-feige/", abstract = "Given a collection {\em F\/} of subsets of S = {1,...,n}, set cover is the problem of selecting as few as possible subsets from {\em F\/} such that their union covers S,, and max k-cover is the problem of selecting k subsets from {\em F\/} such that their union has maximum cardinality. Both these problems are NP-hard. We prove that (1 - o(1)) ln n is a threshold below which set cover cannot be approximated efficiently, unless NP has slightly superpolynomial time algorithms. This closes the gap (up to low-order terms) between the ratio of approximation achievable by the greedy alogorithm (which is (1 - o(1)) ln n), and provious results of Lund and Yanakakis, that showed hardness of approximation within a ratio of {\em log2 n/2\≃0.72 \/} ln n. For max k-cover, we show an approximation threshold of (1 - 1/e)(up to low-order terms), under assumption that {\em P\≠NP \/}.", acknowledgement = ack-nhfb, keywords = "algorithms; performance; theory", subject = "{\bf F.1.2} Theory of Computation, COMPUTATION BY ABSTRACT DEVICES, Modes of Computation, Probabilistic computation. {\bf F.2.2} Theory of Computation, ANALYSIS OF ALGORITHMS AND PROBLEM COMPLEXITY, Nonnumerical Algorithms and Problems, Computations on discrete structures. {\bf F.1.3} Theory of Computation, COMPUTATION BY ABSTRACT DEVICES, Complexity Measures and Classes.", } @InProceedings{KucEtAl93, author = "N. Kuck and M. Middendorf and H. Schmeck", title = "Generic Branch-and-Bound on a Network of Transputers", editor = "R. Grebe and others", pages = "521--535", booktitle = "Transputer Applications and Systems", year = 1993, publisher = "IOS Press", annote = "Guter Artikel, Lastverteilung lokal, adaptiv, Algorithmen geneisch, TSP , Set Cover, hybride Tiefen/besten-suche. Mein Senf zum Code: Kein konsequentes ANSI C; interfaces haben oft recht viele Parmeter also u.u. ineffizient. Selbst eine Referenz auf die globalen Daten wird immer mit uebergeben also old fashionel structured programming; incumbent ist ziemlich festgeklopft. immer eine minimale Loesung suchen." } @InProceedings{But94a, author = "R. Butenuth and S. Gilles", title = "{C\sc OSY} --- ein {Betriebssystem} f{\"u}r hochparallele {Computer}", booktitle = "Transputer Anwender Treffen", address = "Aachen", year = 1994 } @Article{ButHei96a, author = "R. Butenuth and H.-U. Hei{\"s}", title = "Skalierbare Gruppenkommunikation in Netzen mit beliebiger Topologie", journal = "SIGOPS", year = 1996 } @InProceedings{Hen93, author = "D. Henrich", title = "Initialization of parallel branch-and-bound algorithms", number = 2, booktitle = "International Workshop on Parallel Processing for Artificial Intelligence", year = 1993, publisher = "Elsevier", address = "Chambery" } @InProceedings{Hen94a, author = "D. Henrich", title = "Load Balancing for Data Parallel Branch-and-Bound", booktitle = "International Conference Massively Parallel Processing Applications and Development", pages = "227--234", year = 1994, publisher = "Elsevier", address = "Delft" } @InProceedings{Hen94as, author = "D. Henrich", title = "Load Balancing for Data Parallel Branch-and-Bound", booktitle = "Int. Conf. Massively Parallel Processing", year = 1994, publisher = "Elsevier" } @PhdThesis{Hen94b, author = "D. Henrich", title = "Lastverteilung f{\"u}r Branch-and-bound auf eng-gekoppelten Parallelrechnern", school = "Universit{\"a}t Karlsruhe", type = "Dissertation", year = "1994" } @PhdThesis{Hen94be, author = "D. Henrich", title = "Lastverteilung f{\"u}r Branch-and-bound auf eng-gekoppelten Parallelrechnern", school = "Universit{\"a}t Karlsruhe", year = "1994" } @InProceedings{Hen95a, author = "D. Henrich", title = "Local load balancing according to a simple liquid model", series = "PARS Mitteilungen", booktitle = "PARS Workshop", year = 1995, address = "Stuttgart", annote = "Echte Teilmenge von paper fuer Journal of Parallel Algorithms and Applications." } @Article{Hen95b, author = "D. Henrich", title = "The Liquid Model Load Balancing Method", journal = "Journal of Parallel Algorithms and Applications", year = 1995, note = "Special Issue on Algorithms for Enhanced Mesh Architectures", annote = "Obermenge von Hen95a" } @Article{HarHarTri00, author = "S. Harizououlos and C. Hariazakis and P. Triantafillou", title = "Hierarchical Caching and Prefetching for Continous Media Servers with Smart Disks", journal = "IEEE Concurrency", year = 2000, month = "July--September", annote = "Praktikerpapier. Sweep/Scan stategie grouped periodic multiround prefetching. Empirische Erkenntisse wann es nichts mehr bring batches groesser zu machen" } @InProceedings{Luk96, author = "P. Lukowicz", title = "A concept for an opto electronic smart pixel based concurrent read concurrent write shared memory", booktitle = "Third International Conference on Massively Parallel Processing Using Optical Interconnections", year = 1996, address = "Maui, Hawaii" } @Unpublished{Min94, author = "T. Minkwitz", title = "Personal communication", note = "Department of Informatics, University of Karlsruhe", year = 1994 } @Unpublished{Min95, author = "T. Minkwitz", title = "Personal communication", note = "Department of Informatics, University of Karlsruhe", year = 1995 } @PhdThesis{Non96, author = "A. Nonnenmacher", title = "Fl{\"u}ssigkristallsimulation mit automatischem Diffenzieren und Intervallarithmetik", school = "Universit{\"a}t Karlsruhe", year = 1996, type = "Dissertation", annote = "Anwengung von B-u-B und Tiefensuche zur Suche globaler und lokaler Optima nichtlinearer Funktionen." } @Article{Han80, author = "E. Hansen", title = "Global Optimization using Interval Analysis -- the Multidimensional Case", journal = "Numerische Mathematik", year = 1980, volume = 34, pages = "247--270" } %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Parallele Suche sonstiges @InProceedings{SpeMonVor87, author = "E. Speckenmeyer and B. Monien and O. Vornberger", title = "Superlinear Speedup for Parallel Backtracking", pages = "985--993", ISBN = "3-540-18991-2", editor = "C. D. {Houstis, E. N.; Papatheodorou, T. S.; Polychronopoulos}", booktitle = "Proceedings of the 1st International Conference on Supercomputing", address = "Athens, Greece", month = jun, year = "1987", series = "LNCS", number = "297", publisher = "Springer", } @Article{BoeSpe96, author = "M. B{\"o}hm and E. Speckenmeyer", institution = "Informatik, Universit{\"a}t zu K{\"o}ln", journal = "Annals of Mathematics and Artificial Intelligence", title = "A Fast Parallel {SAT}-Solver -- Efficient Workload Balancing", volume = 17, pages = "381--400", year = 1996, crindex = "72k,15,zpr94-159.ps.gz", annote = "We present a fast parallel SAT-solver on a message based MIMD machine. The input formula is dynamically divided into disjoint subformulas. Small subformulas are solved by a fast sequential SAT-solver running on every processor, which is based on the Davis-Putnam procedure with a special heuristic for variable selection. The algorithm uses optimized data structures to modify boolean formulas.
Additionally efficient workload balancing algorithms are used, to achieve a uniform distribution of workload among the processors.We consider the communication network topologies $d$-dimensional processor grid and linear processor array. Tests with up to 256 processors have shown very good efficiency-values ($>0.95$).", } @TechReport{BoeSpe94, author = "M. B{\"o}hm and E. Speckenmeyer", title = "A Fast Parallel {SAT}-Solver -- Efficient Workload Balancing", institution = "Universit{\"a}t K{\"o}ln", year = 1994, number = "94.159", annote = "Auch in Annals of Math. and AI. Detaillierte Beschreibung der Implemenitierung. Die seq. Datenstrukturen sind ziemlich gut. -> SA. Lastverteilung etwas ad hoc, kann ich besser ? Fuer jede Dimension: Prefixsumme der Last. Durchschnitt berechnen Ring formig verschieben. Zur Lastabschaetzung wird heuristisch bestimmter Exponent hoch anzahl verbleibender Variablen verwendet. Effiziente Ausfuehrungszeiten auf 256 PEs ist ca. 150s" } @InProceedings{BoeSpe94b, author = "M. B{\"o}hm and E. Speckenmeyer", title = "Effiziente {L}astausgleichsverfahren", pages = "53--60", booktitle = "Transputer Anwender Treffen", year = 1994, publisher = "IOS Press", address = "Aachen", annote = "Aehnlicch TR aber konsentriert auf lastverteilung. Feedback Vertex Set Problem: wievile Kanten entfernen, damit Kreisfrei" } @InProceedings{CunCun94, author = "V. Cung and B. L. Cun", title = "An Efficient Implementation of Parallel {A*}", booktitle = "First Canada France Conference on Parallel and Distributed Computing", year = 1994, annote = "shared memory. Zentraler treap fuer open kann deleteMin und Search. Begrenzt paralleler Zugriff durch partial locking. Sie kriegen Speicherprobleme, Speedup kann man nicht ablesen aber mehr als 4 auf 8 PE Sequent und 2-5 auf KSR1 sind nicht drin." } @InProceedings{DutMah93, author = "S. Dutt and M. R. Mahapatra", title = "Parallel {A*} Algorithms and their Performance on Hypercube Multiprocessors", booktitle = ipps, year = 1993, address = "Newport Beach", annote = "Beispiel, das jemand Multiprocessor fuer Distributed Memory gebraucht (Hypercube)! Lokale Duplicate detection wird als parallel verkauft. neue bounds werden gebroadcasted! 2 Arten von Nachbarschaftskommunikation: wird die Last irgendwo Knapp (Schwelle), so wird lokal neighborhood averaging durchgefuehrt. Hat ein PE deutlich schlechtere Knoten als sein Nachbar (adhoc Kriterium) so werden einige gute Knoten abgegeben. Interessante Initialisierung ohne KOmm: Generiere kurze Liste von Knoten und spalte dann in zwei Teile wiederhole bis Symmetrie gebrochen." } @InProceedings{HerEtAl96, author = "K. T. Herley and A. Pietracaprina and G. Pucci", title = "Fast Deterministic Backtrack Search", booktitle = "ICALP", year = 1996, publisher = "Springer", address = "Paderborn", pages = "598--609", annote = "Abgedrehter CRCW Algorithmus mit Zeitbedarf O((n/p + h)logloglog p). Hinweis auf 'approximate prefix sum'" } @InProceedings{MahDut96, author = "N. R. Mahapatra and S. Dutt", title = "Random Seeking: A General, Efficient, and Informed Randomized Scheme for Dynamic Load Balancing", pages = "??", booktitle = "International Parallel Processing Symposium", year = 1996, annote = "Etwas abstruse Variante von Luelings Algorithmus fuer par. B&B. Nette Anwendungsbeispiele: Integer Linear Programming. Hinweis auf Beispielproblemressource." } @InProceedings{HuaDav89, author = "S. Huang and L. S. Davis", title = "Parallel Iterative A* Search: An Admissible Distributed Heuristic Search Algorithm", pages = "23--29", booktitle = "International Joint Conference on AI", year = 1989, annote = "Verteilte PQ aber sobald alle PEs nur noch spekulative Knoten auswerten, wird synchronisiert, ein neuer incumbent berechnet und zwischendurch generierten Knoten round-robin maessig verteilt." } @InProceedings{KakPer92, author = "C. Kaklamanis and G. Persiano", title = "Branch-and-Bound and Backtrack Search on Mesh-Connected Arrays of Processors", booktitle = spaa, year = 1992, annote = "Betrachtet nur Baeuume der groesse O(n). Nutzt Hilbert Kurven aber kennt Miller Stout nicht. Benutzt sowas wie lokales Rendevous. ", address = "San Diego, CA, 29 June -- 1 July", publisher = "ACM, New York", } @Article{KakPer94, author = "C. Kaklamanis and G. Persiano", title = "Branch-and-Bound and Backtrack Search on Mesh-Connected Arrays of Processors", journal = "Mathematical Systems Theory", year = 1994, volume = 27, pages = "471--489", annote = "Full Version des SPAA Papers, Hilbert wird nun zitiert (1 Fehler pro Wort :-)." } @InCollection{PowEtAl90, author = "Curt Powley and Chris Ferguson and Richard E. Korf", editor = "Vipin Kumar and P. S. Gopalkrishnan and Laveen N. Kanal", title = "Parallel Heuristic Search: Two Approaches", booktitle = "Parallel Algorithms for Machine Intelligence and Vision", pages = "42--65?", publisher = "Springer-Verlag", month = mar, year = "1990", } @InProceedings{WuKun91, author = "I. C. Wu and H. T. Kung", title = "Communication Complexity of Parallel Divide-and-Conquer", pages = "151--162", booktitle = "32nd Symposium on Foundations of Computer Science", address = "San Juan, Puerto Rico, 1--4 October", publisher = "IEEE, Los Alamitos, CA", year = 1991, annote = "Divide and conque laesst sich hier auch als Baumsuche auffassen. Vollstaendig verbunden. Lower bound fuer max PE Last und Kommunikationskosten. Beiweis geht ueber 6 engbedruckte Seiten. Scheint nur fuer deteministische LV zu gelten Zitiert Finkel Manber, Rao Kumar und Zhang. LV Algotithmus arbeitet mit globalem Pool. Mein SIMD Algorithmus laesst sich als effiziente Implementation dieses Schemas auffassen. Auch gewisse Verwandschaft zu Global Round Robin. Aber Kumar zitiert ihn nicht." } @Book{Pop34, author = "K. R. Popper", title = "Logik der Forschung", publisher = "Springer", year = 1934, note = "English Translation: {\emph{The Logic of Scientific Discovery}}, Hutchinson, 1959" } @InProceedings{BeiSib00, author = "Beier, R. and Sibeyn, J. F. ", title = "A Powerful Heuristic for Telephon Gossiping", booktitle = "7th Colloquium on Structural Information and Communication Complexity", pages = "17-35", year = 2000 } %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Theorie parallele Suche @inproceedings{pamoz, author = {Konstantin Popov}, title = {A Parallel Abstract Machine for the Thread-Based Concurrent Constraint Language {Oz}}, booktitle = {Workshop On Parallism and Implementation Technology for (Constraint) Logic Programming Languages}, editor = {In\^es de Castro Dutra and V{\'\i}tor Santos Costa and Fernando Silva and Enrico Pontelli and Gopal Gupta}, year = {1997}, } @Article{LinYan95, author = "W-M. Lin and B. Yang", title = "Probabilistic Performance Analysis for Parallel Search Techniques", journal = "International Journal of Parallel Programming", volume = "23", number = "2", pages = "161--189", month = apr, year = "1995", coden = "IJPPE5", ISSN = "0885-7458", bibdate = "Sat Apr 26 11:36:49 MDT 1997", acknowledgement = ack-nhfb, affiliation = "Univ of Texas", affiliationaddress = "San Antonio, TX, USA", classification = "721.1; 722.4; 921.6; 922.1; C1180 (Optimisation techniques); C4240P (Parallel programming and algorithm theory); C5440 (Multiprocessing systems); C6170K (Knowledge engineering techniques)", corpsource = "Div. of Eng., Texas Univ., San Antonio, TX, USA", journalabr = "Int J Parallel Program", keywords = "computation steps; Computational methods; constraint handling; Constraint satisfaction problem; constraint satisfaction problem solving; Constraint theory; depth first search; Depth first search; Load balancing activity; load-balancing; parallel algorithms; Parallel processing systems; parallel search techniques; Parallel search techniques; Performance; performance evaluation; probabilistic analysis; Probabilistic performance analysis; probabilistic performance analysis; Probability; probability; Problem solving; problem solving; resource allocation; Shared memory multi processor systems; shared memory multi-processor systems; shared memory systems; tree searching", treatment = "T Theoretical or Mathematical", } @InProceedings{RTAS00*23, author = "P. Bosch and S. Mullender", title = "Real-Time Disk Scheduling in a Mixed-Media File System", pages = "23--33", booktitle = "Proceedings of the Sixth {IEEE} Real-Time Technology and Applications Symposium ({RTAS} '00)", ISBN = "0-7695-0713-X", month = jun, publisher = "IEEE", address = "Washington - Brussels - Tokyo", year = "2000", } @PhdThesis{Bos99, author = "H. G. P. Bosch", title = "Mixed-Media File Systems", school = "University of Twente, Netherlands", year = 1999 } @Article{BosEtAl92, title = "{PARTHENON}: {A} Parallel Theorem Prover for Non-{Horn} Clauses", author = "S. Bose and E. M. Clarke and D. E. Long and S. Michaylov", journal = "Journal of Automated Reasoning", pages = "153--181", month = apr, year = "1992", volume = "8", number = "2", } @PhdThesis{Ert92, author = "W. Ertel", title = "Parallele Suche mit randomisiertem Wettbewerb in Inferenzsystemen", school = "TU M{\"u}nchen", type = "Dissertation", year = 1992 } @PhdThesis{Ert92e, author = "W. Ertel", title = "Parallele Suche mit randomisiertem Wettbewerb in Inferenzsystemen", type = "Dissertation", school = "TU M{\"u}nchen", year = 1992 } @InProceedings{PraAgrAbb98, author = "S. Prabhakar and D. Agrawal and A. E. Abbadi", title = "Efficient Disk Allocation for Fast Similarity Searching", pages = "78--79", booktitle = "10th ACM Symposium on Parallel Algorithms and Architectures", annote = "nearest neighbor" } @InProceedings{JanEtAl87, author = "V. K. Janakiram and D. P. Agrawal and R. Mehotra", title = "Randomized Parallel Algorithms for {P}rolog Programs and Backtracking Applications", pages = "278--281", booktitle = icpp, year = 1987, annote = "Vollstaendig zufaelliges Traversieren des Baums durch unabhaengige Agenten. Modifikation: Toplevels des Baums durch zentraliesierten Scheduler verwalten. Modell fur Zufallssuchbaeume: Jeder Knoten hat eine Verzweigungswahrscheinlichkeit fur jeden moeglichen Grad. (0 verboten) i.allg. kann die Wahrscheinlichkeit von der Tiefe abhangen. Aber Knoten auf einer Ebene muessen unabhaengig sein. Mache das bis zu einer festen Tiefe. Baeume? Branching process? Eine weitere Verteilungsfunktion legt fest, welche Blaetter Loesungen sind (alle in gleicher Tiefe. Wenn man will kann man an der Mathe einiges zerpfluecken. Sie behaupten sie haetten cutoff Funktionen modelliert. Aber Informationsfluss durch den Baum findet nicht statt." } @Article{JanEtAl88, author = "V. K. Janakiram and E. F. Gehringer and D. P. Agrawal and R. Mehotra", title = "A Randomized Parallel Branch-and-Bound Algorithm", journal = ijpp, year = 1988, volume = 17, number = 3, pages = "277--301", annote = "best first. Beweise nicht verstanden. Shared memory. Wenig Prozessoren." } @InProceedings{Nat89, author = "K. S. Natarajan", title = "Expected Performance of Parallel Search", volume = "III", pages = "121--125", booktitle = icpp, year = 1989, annote = "Scheinbar das gleiche wie Janakiram, zitiert ihn aber nicht. Referenz auf Buch ueber order statistics." } @Book{Pea84, author = "Judea Pearl", title = "Heuristics", publisher = "Addison Wesley", year = 1984, annote = "Viele Theorie sachen. Z.B. Beispiele fuer polynomielle Baumsuche" } @TechReport{Jai94, author = "S. Jain", title = "Branch and Bound on the Network Model", institution = "University of Singapore", year = 1994, annote = "Bei sehr grosser Last reicht es, nur selten etwas zu Verschicken um aehnliche Leistung wie Karp/Zhang zu erreichen. sanjay@iss.nus.sg" } @TechReport{GarKoe98, author = "N. Garg and J. K{\"o}hnemann", title = "Faster and Simpler Algorithms for Multicommodity Flow and other Fractional Packing Problems", institution = "MPII", year = "1998??" } @InProceedings{BeiVoe03, author = "R. Beier and B. V{\"o}cking", title = "Random Knapsack in Expected Polynomial Time", booktitle = "35th ACM Symposium on Theory of Computing", year = 2003 } @PhdThesis{Zie01, author = "M. Ziegelmann", title = "Constrained Shortest Paths and Related Problems", school = "Saarland University", year = 2001 } @InProceedings{SpiTen01, author = "D. Spielman and S.-H. Teng", title = "Smoothed analysis of algorithms: why the simplex algorithm usually takes polynomial time", booktitle = "33rd {ACM} Symposium on Theory of Computing", year = "2001", pages = "296--305", year = "2001", } @article{KaRi99, author = "A. Kapoor and R. Rizzi", title = "Edge-coloring bipartite graphs", journal = "Journal of Algorithms", volume = 34, number = 2, pages = "390--396", year = 2000, } @Article{ColHop82, author = "Richard Cole and John Hopcroft", title = "On edge coloring bipartite graphs", journal = "SIAM Journal on Computing", volume = "11", number = "3", pages = "540--546", year = "1982", coden = "SMJCAT", ISSN = "0097-5397 (print), 1095-7111 (electronic)", mrclass = "68E10 (05C15 68C25)", mrnumber = "83h:68101", bibdate = "Sat Jan 18 18:03:50 MST 1997", acknowledgement = ack-nhfb, } @Article{ColOstSch00, author = "R. Cole and K. Ost and S. Schirra", title = "Edge-Coloring Bipartite Multigraphs in {$O(E\log D)$} Time", journal = "Combinatorica", pages = "5--12", volume = 21, number = 1, year = 2000 } @Article{LevPipVal81, author = "G. Lev and N. Pippenger and L. Valiant", title = "A Fast Parallel Algorithm for Routing in Permutation Networks", journal = "IEEE Trans. on Comp.", volume = "C-30, 2", year = "1981", pages = "93--100", references = "0", country = "USA", language = "English", enum = "3944", descriptors = "Interconnection network; parallel computing; routing; algorithm;", date = "09/03/90", by_date = "Uhl", revision = "21/04/91", by_rev = "Le", location = "UniDo-ESV", annote = "An algorithm is given for routing in permutation networks-that is, for computing the switch settings that implement a given permutation. The algorithm takes serial time or parallel time .The se time bounds may be reduced by a further logarithmic factor when all of the switch sizes are integral powers of two. edge coloring for bipartite graphs", } @inproceedings{ goodrich92planar, author = "Goodrich", title = "Planar Separators and Parallel Polygon Triangulation (Preliminary Version)", booktitle = "{STOC}: {ACM} Symposium on Theory of Computing ({STOC})", year = "1992", url = "citeseer.nj.nec.com/goodrich92planar.html" } @Article{Shr98, author = "A. Schrijver", title = "Bipartite Edge Coloring in $O(\Delta m)$ Time", journal = "SIAM J. Computing", year = 1998, volume = 28, number = 3, pages = "841--846", annote = "genauer O(m(log Delta + sum_i p_i/\prod_{j # Copyright (C) 2007-2010 Andreas Beckmann # # Distributed under the Boost Software License, Version 1.0. # (See accompanying file LICENSE_1_0.txt or copy at # http://www.boost.org/LICENSE_1_0.txt) ############################################################################ TOPDIR ?= $(CURDIR) main: library include make.settings SUBDIRS = common io mng containers algo stream lib utils contrib SUBDIRS-lib: $(SUBDIRS:%=lib-in-%) SUBDIRS-tests: $(SUBDIRS:%=tests-in-%) SUBDIRS-clean: $(SUBDIRS:%=clean-in-%) # compute STXXL_CPPFLAGS/STXXL_LDLIBS for stxxl.mk # don't include optimization, warning and debug flags stxxl_mk_cppflags += $(STXXL_CPPFLAGS_CXX) stxxl_mk_ldlibs += $(STXXL_LDLIBS_CXX) stxxl_mk_cppflags += $$(STXXL_CPPFLAGS_STXXL) stxxl_mk_ldlibs += $$(STXXL_LDLIBS_STXXL) ifeq ($(strip $(USE_PMODE)),yes) stxxl_mk_cppflags += $$(STXXL_CPPFLAGS_PARALLEL_MODE) stxxl_mk_ldlibs += $$(STXXL_LDLIBS_PARALLEL_MODE) endif ifeq ($(strip $(USE_MCSTL)),yes) stxxl_mk_cppflags += $$(STXXL_CPPFLAGS_MCSTL) stxxl_mk_ldlibs += $$(STXXL_LDLIBS_MCSTL) endif ifeq ($(strip $(USE_BOOST)),yes) stxxl_mk_cppflags += $$(STXXL_CPPFLAGS_BOOST) stxxl_mk_ldlibs += $$(STXXL_LDLIBS_BOOST) endif # dummy target for initial creation of make.settings.local config: lib-in-lib: @# nothing to compile lib-in-%: $(MAKE) -C $* lib build-lib: SUBDIRS-lib $(RM) $(LIBNAME).stamp $(MAKE) -C lib touch $(LIBNAME).stamp ifeq (,$(wildcard lib/lib$(LIBNAME).$(LIBEXT))) $(LIBNAME).stamp: build-lib else $(LIBNAME).stamp: $(MAKE) -f Makefile.gnu build-lib endif build-lib-utils: $(LIBNAME).stamp $(MAKE) -C common tools $(MAKE) -C utils tools $(MAKE) -C io tools $(MODENAME).mk: $(RM) $(MODENAME).mk.tmp echo 'STXXL_CXX = $(COMPILER)' >> $(MODENAME).mk.tmp echo 'STXXL_CPPFLAGS = $(stxxl_mk_cppflags)' >> $(MODENAME).mk.tmp echo 'STXXL_LDLIBS = $(stxxl_mk_ldlibs)' >> $(MODENAME).mk.tmp echo 'STXXL_CPPFLAGS_STXXL = $(STXXL_SPECIFIC)' >> $(MODENAME).mk.tmp echo 'STXXL_LDLIBS_STXXL = $(STXXL_LDFLAGS) $(STXXL_LDLIBS)' >> $(MODENAME).mk.tmp echo 'STXXL_LIBDEPS = $(STXXL_LIBDEPS)' >> $(MODENAME).mk.tmp echo 'STXXL_CPPFLAGS_PARALLEL_MODE = $(PARALLEL_MODE_CPPFLAGS)' >> $(MODENAME).mk.tmp echo 'STXXL_LDLIBS_PARALLEL_MODE = $(PARALLEL_MODE_LDFLAGS)' >> $(MODENAME).mk.tmp echo 'STXXL_CPPFLAGS_MCSTL = $(MCSTL_CPPFLAGS)' >> $(MODENAME).mk.tmp echo 'STXXL_LDLIBS_MCSTL = $(MCSTL_LDFLAGS)' >> $(MODENAME).mk.tmp echo 'STXXL_CPPFLAGS_BOOST = $(BOOST_COMPILER_OPTIONS)' >> $(MODENAME).mk.tmp echo 'STXXL_LDLIBS_BOOST = $(BOOST_LINKER_OPTIONS)' >> $(MODENAME).mk.tmp echo 'STXXL_WARNFLAGS = $(WARNINGS)' >> $(MODENAME).mk.tmp echo 'STXXL_DEBUGFLAGS = $(DEBUG)' >> $(MODENAME).mk.tmp cmp -s $(MODENAME).mk.tmp $(MODENAME).mk || mv $(MODENAME).mk.tmp $(MODENAME).mk $(RM) $(MODENAME).mk.tmp .PHONY: $(MODENAME).mk library: build-lib library_utils: $(LIBNAME).stamp build-lib-utils $(MODENAME).mk # skip recompilation of existing library library-fast: ifeq (,$(wildcard lib/lib$(LIBNAME).$(LIBEXT))) library-fast: library_utils endif ifneq (,$(wildcard .svn)) lib-in-common: common/version_svn.defs GET_SVNVERSION ?= LC_ALL=POSIX svnversion $(realpath $1) GET_SVN_INFO ?= LC_ALL=POSIX svn info $(realpath $1) GET_SVN_INFO_SED ?= sed GET_SVN_INFO_DATE ?= $(call GET_SVN_INFO, $1) | $(GET_SVN_INFO_SED) -n -e '/Last Changed Date/{' -e 's/.*: //' -e 's/ .*//' -e 's/-//g' -e 'p' -e '}' GET_SVN_INFO_REV ?= $(call GET_SVN_INFO, $1) | $(GET_SVN_INFO_SED) -n -e '/Last Changed Rev/s/.*: //p' GET_SVN_INFO_BRANCH ?= $(call GET_SVN_INFO, $1) | $(GET_SVN_INFO_SED) -n -e '/URL/{' -e 's/.*\/svnroot\/stxxl//' -e '/branches/s/\/branches\///p' -e '}' STXXL_SVN_BRANCH := $(shell $(call GET_SVN_INFO_BRANCH, .)) ifeq (,$(strip $(shell svnversion . | tr -d 0-9))) # clean checkout - use svn info STXXL_VERSION_DATE := $(shell $(call GET_SVN_INFO_DATE, .)) STXXL_VERSION_SVN_REV := $(shell $(call GET_SVN_INFO_REV, .)) else # modified, mixed, ... checkout - use svnversion and today STXXL_VERSION_DATE := $(shell date "+%Y%m%d") STXXL_VERSION_SVN_REV := $(shell $(call GET_SVNVERSION, .)) endif # get the svn revision of the MCSTL, if possible ifneq (,$(strip $(MCSTL_ROOT))) ifneq (,$(wildcard $(MCSTL_ROOT)/.svn)) ifeq (,$(strip $(shell $(call GET_SVNVERSION, $(MCSTL_ROOT)) | tr -d 0-9))) # clean checkout - use svn info MCSTL_VERSION_DATE := $(shell $(call GET_SVN_INFO_DATE, $(MCSTL_ROOT))) MCSTL_VERSION_SVN_REV := $(shell $(call GET_SVN_INFO_REV, $(MCSTL_ROOT))) else # modified, mixed, ... checkout - use svnversion and today MCSTL_VERSION_DATE := $(shell date "+%Y%m%d") MCSTL_VERSION_SVN_REV := $(shell $(call GET_SVNVERSION, $(MCSTL_ROOT))) endif endif endif .PHONY: common/version_svn.defs common/version_svn.defs: $(RM) $@.$(LIBNAME).tmp echo '#define STXXL_VERSION_STRING_DATE "$(STXXL_VERSION_DATE)"' >> $@.$(LIBNAME).tmp echo '#define STXXL_VERSION_STRING_SVN_REVISION "$(STXXL_VERSION_SVN_REV)"' >> $@.$(LIBNAME).tmp $(if $(STXXL_SVN_BRANCH), echo '#define STXXL_VERSION_STRING_SVN_BRANCH "$(STXXL_SVN_BRANCH)"' >> $@.$(LIBNAME).tmp) $(if $(MCSTL_VERSION_SVN_REV), echo '#define MCSTL_VERSION_STRING_DATE "$(MCSTL_VERSION_DATE)"' >> $@.$(LIBNAME).tmp) $(if $(MCSTL_VERSION_SVN_REV), echo '#define MCSTL_VERSION_STRING_SVN_REVISION "$(MCSTL_VERSION_SVN_REV)"' >> $@.$(LIBNAME).tmp) cmp -s $@ $@.$(LIBNAME).tmp || mv $@.$(LIBNAME).tmp $@ $(RM) $@.$(LIBNAME).tmp endif tests-in-%: library-fast $(MAKE) -C $* tests tests: SUBDIRS-tests clean-in-%: $(MAKE) -C $* clean clean: SUBDIRS-clean $(RM) common/version_svn.defs $(RM) $(LIBNAME).stamp $(MODENAME).stamp $(MODENAME).mk $(MODENAME).mk.tmp getmodesuffix: @echo "$(LIBEXTRA)" ifneq (,$(wildcard .svn)) VERSION ?= $(shell grep 'define *STXXL_VERSION_STRING_MA_MI_PL' common/version.cpp | cut -d'"' -f2) PHASE ?= snapshot DATE ?= $(shell date "+%Y%m%d") REL_VERSION := $(VERSION)$(if $(strip $(DATE)),-$(DATE)) release: $(RM) -r reltmp stxxl-$(REL_VERSION).tar.gz stxxl-$(REL_VERSION).zip mkdir reltmp svn export . reltmp/stxxl-$(REL_VERSION) $(RM) -r reltmp/stxxl-$(REL_VERSION)/homepage echo '#define STXXL_VERSION_STRING_PHASE "$(PHASE)"' > reltmp/stxxl-$(REL_VERSION)/common/version.defs $(if $(strip $(DATE)),echo '#define STXXL_VERSION_STRING_DATE "$(DATE)"' >> reltmp/stxxl-$(REL_VERSION)/common/version.defs) cd reltmp && tar cf - stxxl-$(REL_VERSION) | gzip -9 > ../stxxl-$(REL_VERSION).tar.gz && zip -r ../stxxl-$(REL_VERSION).zip stxxl-$(REL_VERSION)/* $(RM) -r reltmp @echo @echo "Your release has been created in stxxl-$(REL_VERSION).tar.gz and stxxl-$(REL_VERSION).zip" @echo "The following files are modified and not committed:" @svn status -q endif .PHONY: main config library library-fast tests clean release stxxl-1.3.1/images/0000755000175000017500000000000011536252420013757 5ustar andreasandreasstxxl-1.3.1/images/layer_diagram.png0000644000175000017500000025573511437146445017317 0ustar andreasandreasPNG  IHDR=`sBIT|d pHYs  tEXtSoftwarewww.inkscape.org< IDATxux D A -u uըR!cF|9gfݮ{$2$Ivl`&ðAA@1/Xe."$Ix q8  N~ɲ|'I$IwmM-q SK,06 AAɲLcm95הR@inJ&%9F%IyxOÈA46J2?$I;fTAַZok >(g ->UKy 'T:;{sSʿnk ᢐ>i̭],4jlj1u,pJs(!(̬(:FY~[8{;Zeq:eyʶ_VהQ{\ꪊ1A042%9'(O:Lm1cxL-;L˲Lj˴o8s+'ͬh-'7yRn苳ϰN]GuY65 ;v8R'0Ev EG,J3+G=Cq175֒"k01'0}7M$ZAz }+_2+_8;s%G!uGV]kV6sHV6$i 鮮'=W~ *?ֶH,pj PQxg!xܝxN֒L^>̬2y!>!1t8U̧.պEf4FHSSUI&&m@$F .MJ̴ ïjU*H&;qY=AZc޼z{{K$sa. +ۖvw1%2i8z>W>5T-߀N504bO8PshJTYNvvUje;t=An"z"e4JNDya{#I2y!N^aʾ$d}@$ QVf&d]tQU$_u|$: Ts.gJ`bnZCey.K} &h^!)80wd`$<*U 1JoP'=Eul땄Ă#88m-104Q˙-Wo3+G<(=U%fwDse `TdP_]Bsc-Flퟺ3<ɲJVFdv8m* N"n7ԔPQFc]՝c \Gu33+MmUa:m܃:3vVyLmqNnZ2Nl&fLmq34$gngMzL-l:A` ZS (~:gʭ6UKaf@c}Q4Q[Y܎ʝx6u˔I<P6CA2п/|6t{&4"eBvvWkVScVc``\y6l P뺪f*K2Z 'g))ڱypWh19Mxji2K;ϳninBl5UXW]TRȪj+ 042 zHfO,wW[ooɲ| >H.M&EOx@}{C$<^IӖ4^'= I:cA47h>/e9YNYK^>HA #stm=&zX2G|k Pe)uuGfM$YPsFyUA_Z(/ho5t8KVq#"AtU'sg{lIz$IFM}fBA47rIӶ/FWWI$I >pAcor-#AAV^~JMynۮ%~Hd ,NxO#TL% }Ҏ,_Yf_s~$ `D>Ss[\Fce#fZ] dYEC]9եהR@Ivb-˲,uu uc?#ARW ޒe䅞'=$Ir_ S* HZWW"9֖ ӾCA'GA~A_A_I  HzAAD# B AA /GA~A$=  "A_I  HzAA$ VCZ$)0ؕ$rF0D\%ns 4veʲ|Z Љod$n兲,kt#rF+)eNNOȲ\Qj˲|P ]),gk;aȲSaƮlYS4-h;(rF@CX$se\Q^-rN^>Q|r DY:hJe9]^Y5.,'jt!^#5rF.XY+5~啲,:0/rFQ(~sDVN˲Qn Ӊu,*:C'\Y4̀HseV@߯mJeY>seT\߿5dɲ?`Fy:pN::92:锇蔧:u>)\ܦsyN|Y'ҩsNm:{;96:O֍sSe<^/:oSn9"u{ף$I3OPFyo@0ή^ IqiAsJ 7dSY#L`z&nIFV Ĉ3gA56֓Jl6٠ojO]uXXZs}3j,LL̺?XTmMveP_>Ep67IOߣ7>!#60A.;M^l{T*[}e8$IK[ݏkOZ.{Y|$'(+T|,#I9pWJz63%Ib[Ꭷ153A%ݧ/,S4[rNI+n9 R,X+V/->Se54)I$I Q#}ȱ38"AESc('!b碵E$1J~Tχ.l{dY^[cE/ċK$_ƙt "Grcobai ǟ]ll{$>Agw?:fgo rܒ$I~Yp:$A+B$;sH4·^ƾ#Mw?Ӷ$I]Tm2}l`=U#?m6?8Su5"RH ٚ4c>&5:,ɲIϵ ױn_i(IR9; Gc}g`ho`fDu%IV뭭#^yԶy9>IMOynACFq(} QZOYi! u8z⅋7#^aҳ؃r⼮Ș)+)`ߕ̾ z,mYbe{kqs_JODOmM%FFD_%t!tx2:{i6o`h/EpnXXZ≷`<;nOOC PbJI<ʱvx  7+*e!#:bb\W5~f-tC}mKQg$Iɭc3 u\CMuV٩o]+xa} l^y]w70flKXrop%=QHk:ǒjוulg|Q-vl\J>O$=0{G?przMVz;F&L1y}dҊCIz r3 XғrBIYrrU7>K>=ֶsn׽߽?tHxt7b/Rdͫ? PloH=ugk9 h575}| zSW%#`:TڻV)x fp,H9u46̆?cyaem-Yio_' CCC:ֶڏ/d8!,b2GO?"=-2`kFzey %EyZubٲf]{ֶZ3s\-⵴s[Y]^HY};RY mTWŻOt2Jbmf0熅̹aaud')w?erQ[n乌83 O.RU--Ŗ5pdx.%:fκz{Sf-`ʬrnArRML1ul}ݽJPVRxQM 4qcoN-d'R]U7a#'2~ڵq%Ey8d%P]UFhX{ǨZZرi9IҎ(Z IDATX+BF0;t/+)` a\y͝ј]䦳gIK#G'ģ0`pLROeﶿ)-Χ##cllp `8vG$QA~N:Ņ9X3wJ<û>Miq>ֶy1e<}vyп2|4ڳ#QەsncPzqDgӼ}9tC#c|0|T eyص4 r3013ɝ1f6r9=Iٲe;|dNlGl 8FfZ"iXZ;[sڻ؃4[<}9|`R6e\}ؽO3NQ\ Ù5nM:][VroPW^' _^"*DңǚHXm:$ϚʊR<}2au[rVN[!wl\Ɣ7a``,ˬ[ƁW-`䦳j礞:V1auH;ٝQSp}UFOEYun/@zRwx7՞m[¼Le+)3oČC{7jM-=6?_k9/”ģ$$+~d#.w'^ſzW:_m]\9p^\<祥Y/ zWsIAqaN.est ZhZ8p~.J eEe)Z#&3W$%(kC}R_8P404%$cqg_>5~&^wQ5XW[Łk:Kܙv-i{0:Lilcjfc/~(7>}aG]ýIdLI;2|<$90Zà477w1fzD{tG=Gb4{뎔NV)OJңRicdlw>9sML I?5UA[ msӵ:J| d$w喛1ٝ:bGLTiY,.9$\ 2Z:&o`hHpX:Hp4gW/|9thӓ/JP[j]w玩GpuNZ*K15$=$7s|hš1{:"<p}PT礑xS'c:<7ײ1#AC% KN+ؽO}vz@{%صr2S(.4Tʭmx;RϷR^Zģw\ķo[?Vg;?'ot\WRG]m=egG,-m:y:ulay ]!@谱XZٜq"˝pPׁ4voSkeNf &SRyp!KtHs dSbҡ?「˙$I$m}z%<3m(ˤ$b,,mwtэzvC5qlO÷9_cqX̙PI2&GMԭK%}<+k;{s6dwtΡ}Ay_ضa)9Fe= c[05:RS4\|; ;֐}+{0auyAEYQ]'G415c=2tD 7\lpvfk;]Š~QS9ytyY)/+Ww_&]1ÐeAz=;89,WK4Hcu#aԄY]C9nBrpzrNS-N.;ӉX"<_C<*h{t8Sދᣧu5EkΞn&\cZ)#L݇;֒@UE)> ̘>[X3%(0]e-Iҵ*GgkAzSlԶ dY>$Ib^g8X"5{맳q&k#3-Aٶ?v_]tf{\\.ODheL\$7 HjAA.k u}ʭ=+{y;ui'6q{KA9|@}ף_H'Z0l$"]WS Winj$.v/*U eED۬UG$Brϣoh V,WOGA$j̀nllڇ\ެx_r~bo8@'W"$tظWI e茵A"ΧΧ: :l'61\jAAh%I!0H  pD# B`Tu  H:AA&iOږ$ NeA Jնy-Cadd ԋ e-2#rUuA.UM} Y[t#Ine 6v<̇} DraVypp>?LKd;vP}ؔ!bU^A.ښ :Pʺ 1d]A&I$I_G^U^ZHzɾCx=>F.e>qѯt2|ϳkJ܅tj+Nf ˲,˅} ;؋~݃SqѯRjdYYT-r/1Y\q>i)q1lT|%IA^&!GL8XYr1_3)G9& aYTg*B"9rh;0"rF1777ojr2#~>}J*ʋiii&/'ZZ/=e(.eogmK_Q_WCrB,nQY^LmM /(/- /߿_~f?,- rزg>zTܵo?z3&< u|BSc={͢嵐?~o>)8_C{7XOiq~CMXeG;YeYV2YVMqa6E"]3ʲLJQ,,\6N.&ff&ΘOvFI' q#3~<~%֬c~b 2y:z?yC"]I~imT>x>Fο~IرiKya`c,5wCWB\gg#2-~""'!1TsIsX;8a 9|ZQ{67Ǹ;|f'+=fo(Ϥ/g̛7X+oϾ=\{ˣxx8 #IeY.`͞d˚_L7 y3/yÍw>3/x|&ee //BcL:}גO^ozcgʷ=G\^᳷%'3圏Y-$h9c(-Hv@mm5&H-|N.Ly#MTW`mxT$V6@:zt殇_ᮇ^y5KB!lVCC=SgLfZ"vV7~dilcO3 HIV,#&Z3CC^|쾘m_fW0vՀ W4t4~$bg;)GTW {hO|061%)>#&Ca~9Ʃao9X&FD z&jزLSLL̰spa֕x4t4yYb:bgofnIAn:~x+UK y %l;D`hh]Ȳ̩Dـ9]ݧ/0zlcHbs W 'cwxoHNe_3!~Csr$zf*5~&9TU ز'Vf 9֭ ZsEߴRT3sK}9f)e0_ρ]Xsfͻio!!.xSa͏5#!.7>3sˋzc&Vby; y͟6>bTpvjI<5 IDAT]iCC#b}%|d'rm+ ٱiEY8/@*KFray{jk*IKCj8CFΞ;7/Ad&s$j;w?o`dYf5 $=1`m?w8s w=X+I;^ع;pC1JҒϟfpd ecfaG }9w#O- 1%9!W\RIsIN%r\e%>}Ɇڎ3{ÿݏΎMH8Epyu 6#&{J<}g15 ff8ko}k*K BvAn:.>zmϺ%[T g=>`# 5;6-cԄ̿)bCԞ _fed%~?"l흰ǵ5311;>#ff-II~ALq=Ǣw)V[SIIaNk%RjoeT ՕTZ{GwdzШ491}n׫sO:lrC&w$w7ܼPW[E;5ot֟ݚg_5O*Oݧ JyQTzUKc4U5u/\yJ{@?tՂf f og4Zmȳqt ?o?$>FO#oի+7EuTԙ0M:uF*Wd*x)-.hu:L|-5wĂ-܌DUeBNvϧ?76Rx[RPB6;޿V@j ?QMMu421 tt),&n%R^V9~¸;߇[DG`/ٽe:߮PoQ6RY^ǁ2w%ORCg5de$FOJFɽ\ FSK xミit/%"R UU*+8?j׉:wL՗H04Zi)7YKdgEuU%PG^Ù6STTT?-|K^v:ZTɀSsё'(+-FK[=}2s'ͻ;7TrٷmPlj#s!(RZt Gt6P+>%VA@&Շ߻q!,Y~A*+)BO<%m}C3S(/+FSKqJ~c5>ԵtyMcTUkG./+oT&ê#vxs`ow}ojM76 ?jMuܳIbߝG N'r8q>({di&Dǃ3Iq]}#[6hsҨxw7c7sh^? -m]bc"XrV6N<=-!%֭{G$zl']{9oh8z2ޓo=D5p<V';7!Sg[.ӵp[LwJs3'Zwٹ=U_ɜwǿ7)IqlZ=[̚n':o@?<;O 'Kc`d|nEcޕ~ogO?c߶բsl&܌oLGWWûqINPgK @EUn]8w'lgȩ͎ ޿l\ ?Wv+M_ G0 cuD3e *C^-!uX0i+w|E΄&xF?cdR\eV*ICGTT$(y||mM $߼ H4f{5f̳s^6l jپaƒgFMuFN:uɬ#YSϵ]|]G^|}(0`T΅$۝ِ=X81eq܈ |w0p̭9s|nxK3x\EAnf(,A]S 'o5qipv Gn0Io.Ʒk?l\ya|xܬ`3/|zFhi7 C.1h4O'=5AC"rYߢ._O DGqBz4ƒپmp Tؿg/D샧oP/&7;]Ey0<]=Ckʅ` ;7yUЍkQ,E,H^;2U }T{C_9/VQUE?Z Qx44LKdqeH$14V,۵WПjgLFUۭXjkk7`TVb55ۭWGSK'go"B:7D͗]poHKDM]C4x01k]{WcY6oMz&$_ZRn$< tpO=D4z.~ {ʊ%ޅ.H\Υ3eH$RF<5U߿B30I֯r z$ݼʎq&jܹ  i،D"=CǾۅ37#8sK[4_'#{ֱ8 M-Ο=J~nBLxfx|}ϕeV6N<;b=39=%J5RWiRV Q#iY[W͢l8v`sut (iF54R D"g򜠴&)&[6ջ{ː1ӑJU8}P#Oc2}2L-)BWf m]}JHAMMgDSKu-lAVB,Uhi59!?.y@yf.F8 ab7mUdظ ˁGRUY?r1ohJ`L?:yN a{=vm Ij .?)Z6μl߰+TUU %^]% (̥{QB;7H$zueo׷KPjm!. L%3# [W:AUMb݀WQcc!e[ԒNJ7ʎW#QWݧ;rh+܌HDa3gxS֣S@&󾓸+\CUM ν ɔp&dP?(%ʊ9}t;y9ZtdzvզSop!<'q+ZtvmS>:v&%rpprK .K;GJ%!r35K/#cneOZurSwǿ8QVRLmmGaL]=C5>n4!c3Q%흤D"4/UVVܦk5H@ݺAԹ?{!hhj3kEUUE0L# {M-#ļ>>TCQOI=h"inTB;-&=#F e 0WyH{ _b)d'anio|kfaa z#\R[[WFڟ,ݮn61{Q$߼F~n&6 jIsи#y[EU;q$]G*շIؼMxzғp Ŋ<^!JdabjEt Da~_9JK $Ny;NښjT1c۟ \0Ln^DP).gꯘ»w}a'zPQQƩ#HK[dgb۟hD 0?ޣ(ۅ(+){gB&nZ Mm]߄`Iy]If"Nç;I-zZȞۿ}CSTT9Ν>DKő6~&'$5~2ƦVXv !w?{'wNR)N.>YL{ס^(-)SxD[[͸h˕gxvg3޷95%D2l⾵?}DVZ2&fDPW[+ާkjI5jj9HR^[V6NX8ѣ8y)IqXXq5,kBYHNZ:z2) P"ccבW/ չ6* .΢_!HfEXTj ijUM-m\颾3魥*d%)vnv솖Gj< yr>_ m]}azƔQ /̕ TTdvR).ǎgOۯOFGϐ5a'܈W?G~-nؾ|-߃6%|X2#B8}t's]J%ٵ6=fѯH$R>?+CYa4tذr>a&Wbmī ~DEE<{i.ns!|V44֙?~D@lJ[~CaA~9w='lٽ ^]= }a# }=q3.Mk"59AttL';o>ǀ[rh+'oڶGkMD"ad&uQQQE"y{TTU ޷ҒB|ȩ:sOnų~"*+;!o{rC7l2-__$htu 9}l7E5˷oPǬy->%mٽؽܷk LHuC4zXmҒ.:x+:'6Xbȉ/u>~[5 ANCM"Omz /϶u߉44p ^B]C+Cr1bR6o{GwhbnX g`LLYF9̌$RnP[[_ ͝ `ӚŤ%_W=UU XGkRUY33X|)/㦼ξm+JKPW`ėOyzTWWqߜ ށ&X:kIsN'.#Cyxͫ+W/z'';=[Wpp$y2?#'SfW7U55&M^'8:{s6 G/IMYi;7-?Kk:w@ 1NQ[ۂ QVUQQEK[Fqڍ6 =}EOkK{Tڟ!u+ ?#ZJ M4U5ir6ggX#FYiqSK+fh*x% ƫsǏ02 8oh,_CSu mNnؓPQ^Z$DkL"q%,I;z$?tt:!ry9叵mvgw?f[m{y.̚z9Kk{f[x_]̊?㤧ޤ3snw<8r*/FM] JK HnV+'>/N#7;Lvxu驠4'ND]1h72a_cd3ޭL-HKG~0א6JU>aUeM0| ~oU BGNܸv555}b@7:h H$M,Ay=Jsn^!=5FZ̚ bc"sjE̥ 96ppXuPHjn hirJb{36ZPZYQ.nDfd"&yvq-+± c-(-.Gqb?s{1 ޿ܸ m뾣ָ:6&L,m=*M<ۣjz-ciwdbnr&4 jj*n@"sX3%t C' ֠t6ԯjL,l4ڳgw?^n\<^` pKr,:88ycko!QL^G̬DI$'Oqtm8xۃ֫zϲEsXALi2ӓԬ6]W[[Q\8w;yC؉} ;MPТq9 m]TU8}| }C]GUuWHqn<9}Œ!ZGfVv;u[*J 9E8wW.gqVcrT*#eçСܽbeH._8MMMGNA!>. Į !鏛WӞGJ(7^Ï_WTWq1"x<}%u&<7ϸy-%JڈG@rR š+ rPg`,x1 ޿|U;G M)4Ԧ}/1<No'~ț&%ZYɘg_C"*n]͒khh1uG߾Cƾ@~c%p _[Dȡl^vv<\^S^g߰}2,m6~&w!J7b{صe@cKTUUPƣu{tuo#ii`aeS`_Zԝ[׹B{gM~9QJ/jjJWFg3QS]M\x5u m R/#iH$SyO8KA6d4Ԋ' IDATW~Qۅ312`ڜǣyͲ(+-fλ9"B7zM]@A㛏g0imrWxw2<4%,ULAJ"/s–JpG%Lk۶ >0QOB=lFakLE/}ZUUNEYi5j-GLES&k[& vE4('>6d4uup E O 5܌FW '˨Q 4( 7=+[l}Đ1/<)(yTVG/beȇlQؗ†U_0핅Jo\N7j!ީ;c&iQ`I"'3/ޛB`QڢG=E!QD%O<1N#'I;A16&3=.?EKx+},*j;g`|QA(֪'d s(QD%)qW"iS۹'oo S_HQ}LdêEY򓈱%.rO*@:` 6 -m=:wOyy ׯIua o=`N$"uut[M$_!J$u詪$"5ع=TMn\D=(Q: /*JeԐ(Dw&d7V~AYiNvr#BR5ZVwq+1+TWWqR8=Eb| ͥ {'wd*'` kٽ qWSUUo-6Syù|tFOeE!F ڣlj9)>{QgWHIѝZ#Opt f6F˷#O豝%`Kr؁Mdr)u0aGɼW<}HMjt@<,X]JK޿>FOM wGj $ \x3!=]߿]8tm;P\G}XXٓǸ)?FD"F+HUeÎչ7EvrFϣBO߈.RXA]|ʊG8+%JIyEt%/:8} [~湗?Ю?Jw%&2Ӓ)EKrxwtpo$&*:x o<{$^>wqn{7tt4t9q/wF?~F(+-fUؾ`lu{&> p ģSwD܆ԍI͸hAbF orsJOnrZJk©EEUN}>1e%bɲf<#Bl\T"&*,1DG4@NV*#BMmmM奔_LA+-)j؄عGoXgtisv%]KƵ(<3;(ϡK w4Z ^?hA Hg7۪7'$y0jx{9s|w/>~`3##5A퀫?G祷o 1{ܸvAJe8:{Դy8:p)~2tN 򲰱wf{?άAuKo}ˇ!1Y7 +r/*QQQͻ-˿|L{().@EE0X\8AMuZ:4G\eTVj{\"lVohlƸɯ7;l_im }J[SAiI!ڛӷ>D9s!9o1gƵ TUU`e('?Muc)!_d&r[}΅yN U ۍP\mW8NM,<"%_A|>v$_iA$D2R}7XX;`bf~ FO#ƶ3lm1zF}544 9Gs2Sw`3sigLJRwegW뱰OMXX;չ'jjbrCфЮ?HIFS r:E ('oS ~^ygeb߶U&@GW.(*ȥ0?tͬHIC-Cu~ Zfl9n'!{5YI0p*+hg 3146_{w@Ο9 m?{R>aXT*Ů@G΄&3- ^t=vvy(ueDoH6-J8:{y2c3ȞuTUߗ^ѽtՕ8tbkpv+sכ#r_\:2sR8AՕZn[IܕH\<2qaΞ ˰wrg+xi[(-V?oDC1p=C<:׊~88 b ?!c^hPmx篴DuUCƾq/RMDao_͑=gF4 ݻJz _s?ŻK/qA3Ӻga|j;} A 9=A=)=n;wD"% 5:~-NwHR046Wt5# n%*lk*-)HZήy9Ms{i:ևޝ̎ˉٽ }X$űw16"XJXTVQ^V²Ess~/d'sdzR3zu ͰV;zbaiWuׯgG)-){5Fmj65ƦVxv ":$?-~A(/OfSI`8tظ'Dfm WbյK$ݼo׾7)o=oo#nݨ⏟cfi][V`gw?ΞMD x8vj ZWg.ڼCBkC[qpɝ#{׳'Vs9\ xfMg_''rf @@ -QW[+_}är%W>Y.cbfg ѓrOCfȡhhjƇ+Ht߿%%I42`;ߣ]{7s܌Dw[eEO vn,^0^'0晹`._8_ 3)y=5UU ?CedSfc/r/hͫ9ɳ>=I&fذj"iI8=۩ɾqS^'3= aߺW[QCܕH] Լg.PN}9~p3{JaA.$ݼG0ãSwd2z_N~c)+-䑿뀦.1px;t()7OCƼU_`H($s}뼸]BfZ"3C~'+IN6)7+=Z1{n轢;{NY*_@lMNX"Eyi W(/+!S07Э]++HOIOu'$Q[[9qx+TWUtѓ Vk1:9[߰=DLT( Ih6p `ėH$޽+g14lD@x9]|z7-p&d7v!'FOqo?&6uj-TC2jkk8s-!Xi 7_xmg/I 3-kpZ>~vpw )m)T 5=N: 5u D}0ps$߼JܕHFOc䜞ٲIQځo|$ɂ8s_,۵Ȍ䄫T+$%ܸ0ܚa&frӰk% cZo\T*c3s=x"O$5ޝKam. kh2\|Oy3#ɨB1a55 17@]?A Ua Y|6_Oyw u|lq8^]]B 5݋ۀZJ[TÍܻK&0Nԇtt~qQ8ɍz(!dOh$)Oݕ϶:oh7q32ݛ,Y}ET&c9 ?ҾwB{kbW"2rK 08r!hң8z#eJmXHxj6G?O|EjkkhKAwGt6pr鄺&uu0^|z~ÞG}^{vw `b"-ןϯ75+;W/й[Fgj_*ѣX2Ӓ۷HFZ"WEt zͿ}MeE9 /޲k*8_K[rrć˃F*q5:W@ /5vm;Ey͝q/ 㧾_CEU[X8HlL8jtVvMd2qaamOlx|li<ۂFfg}Faa@ȡs54y_6~.&ʼn9]sxR>򟿹{ M-ohJȡTU53TԱw3Ar!u?ux>$N~OF!-+5sX?Tn|8jWfM-V+XUTpv٧OZںk'<=ڶwS@_\ -jiOh4| >TmQQQU>d2u k0%\XOSKG|R?-~;GWTUH~]}#c7CN=/}a\z+G"ͫ+oRgۺ).Ŷ+g`bfO ڼ?~')-)YFLbD4]:?x.kYd]G=ˡN{Gwùfb|>|} ƦbT&э}G{/JȔ3!{rOۉm._AH$I1x֋)Q8?^y]†SxhsIioDkd . .,^4wڶfIqiIxtN-'Zs #su Svx@"J;cm눻w7>*%܌ ޒ IDATboC*PQVf_ajO ѽ e%~&ZX`LNV*yxwEPQ^JG.ZDQa.EyʈfNYI jŅyxcdbA~^&15TWU :A7jnQA.<0+3K[ r(/[ 3U5ujjIexf6xOl%]zg`DA^60#S/~h(iq .5txT'-m= rHM@KGoތFs %\;/\P/yX!GD"Y sD"?ɉgυd^ wRS]˓+{ {9W4x;:FkrSWOE?h M>,_d$'\cܔ7m' h=) z"6tTDI>͍Iဏm>vkrُi\"lFٲ]hW)Qy*ˊVRk%*Ah* Hs?zx %;3m=\:bqJ(y(+-fܑ ADb%>ť -Ku7 ' eHAO}Q1EYS/Ε vrlJe߶U К#HT%IWI`KA`D"~ꌝ*GNmʰ%J4GNV*-Ѣs |@"lc|Jԓo?U mDb0z$?:l9@ dYx@t8 I"O2f2 ТSs:t폃ͬifm$F$L#+3Ȱ+\ 8MqQ~jL~J$IfF`>GϤ;?T@ @eeaݶ`a5Y>sJOn$I4ӟJ$6QslkC<{ٙ% -rf!IR+ И.CY*@  dݪO9~`cC$'js楷V@p۷u>qY_l$IZ"9aUVČ_%@ 2pt&?ruIjD3[ ?x浯up}@ GFLG㪋?H֘vZ+@%yԐ$ X 0r||;=d@ /O>FKoeY.z=\,510@ :::LZz\ y"=\$I2{9 D/&w:8xani]g,"®8x6Bfz1a6voK6񻗑HBlcVyoyN=Ӟ xx@ u?A5AN=}Lfظ꩝懥 USf 3ӇϾKafH@Ͼ]{uԡݶ# G 4~C0Z$M!UǮH48&r?-?~4|ز(d%_+">6\ң#d雳().[=WY"HnFQYi UW 4 б-?gٱ~#RZ5 E%B4@hBl8[#-}VGW_%I1`ТULJ,;}LfŒ**ˉ K'pr}Lp5CPTV}}3[iQ*@o˗k5$x_[C#Sӣh sd'S\TPq boo`K2 XZWYˤxRz$IrZ8'r=vo}&hBWW3 +cbf%LNbejt6a稹ߣ6c:wd:&|Vm7JTV~h Vx@Tfb"ՔK[UzuIx~ULyUG/=5MPNrB4[ ?Isٱ{4o*y6{:ȯ$#-Q&SRRĦ?;7D~bt TB<vm]l]xqr YHV;dZf?!-tU;^YY?u΍+7 Lu<3=YMC'_PQBzv!6U_>Z):A[wf"ԤuJ#=BnM} ̲ jS͡k:ݺ3z#,؟ϖ:Tu/7Ȱ+ 1_m>;ӪZo Ʀ?@nwL?2T)޸6oEKjץ;Y]<3xm;a(?GOx :࿋B_7+=A}+zomY ܼqYUn݅|c|txsM{Ohߥ{OޘR|®_"/fVeٱak8d=1SЪThHI&%)$l윸@YҒѪޥ ;3ʟ+Uj U] S)ǯXJNw\t( E* >]Tz sXR.ڏBQYgкK%.?7>ҹCw5nME g)Cl5Vaɫ{аX hp?:PW-m5ZzcJWsDWWR_Lcp%6RǢdS-wʽղ6fgFDhu>U˷c`hB=pv»U~uH/raUȄ{ꅷo_PRf(}tZV2*mc7O_mp.C@gf\o^)$I#'w!4hk;'nzefF2Vn>Q^ɏ"3-AT-;U^6]Y֏|URk޽cڰqH |NLѲ޶I19*{WDŽRʞ&b8{۷ _ Ȱun5WYCrs2qZeuy[˹(gZ/ϝ~'AOѵ=3hyHZKzW/sA;5'2JJ @#8ypJY;ov.tB|t([~[ƙ>]hKL2㥳}j "yk\<}iޙT޵m=ʯPXZ3x"KͼJ$[$ 5AW{Eane$k`{'㧿%$M885gػM+??\IQaZagcp;Rg9\8WlZIxf8Fs$af7JS&IJB݁߀xxkn vXmI {-ήdλ/šZV& wvrmʗ***,9Y"j&OBx P^.kW~Z Ib+Ȳ̭|o.^TU9+a9|nc, ?d'/≤EbM'IZ 3rU5y3rMͣO>~!ϐ Lh<=c߽26.̘&G?~WFO]@aB܋ r]=}FLqs1wu'WEy£͠Q37tJqvwU8P:Q߹Eb`hڱ,Z9TcJo! 9^qpnNU7gչk A'^ݫZjG9vg!=}3pyY)qQ7HP)7 jde`JǦV #Bc7B#Iқ,h$I%߄㫐eYmj@ M*OOnLJ%IZ|$rq Ifue*W03 +yF #J|L$YgJ H̀7$Qnq' `,5+tui٦v#/:(dY.e3J+͝t$4+<I,k G -Y˲ɲ$s@oԝE@oYw4,@ 5iʐu,ʲ<Vd=UK@gYeA#?MQz@𬧚>0G B"YՒ$ɠ);$$I#(M;5i$$IR@ jbI#I%I 8LEs8|͎$m$#@P&Yޒ$#0d9*ɲ<h>^K ~z$Ez2R TSp$"$&/!&a )=5@ʚ~ND} 0@o5ie\ 8ʼn V f?o#1fw/J'"$‚R w$Iz$ o*(h0@U.1.pKC#&OYVphآɏºU[go͇O7=t,b#7x*rs2Xd7$_ }|Kf$VFrN[~i xKfq&볰 OMۏϟ>āMDG\cɳ#cŻ\ 8d+NeY޿,&JfJN8`,1">$i3dӐ?>8q`_?|آ ]8k{'HA~FK,7TYp`$IO%hB +E+S?.*eibna0{ (ۈR@GMmYOmCY$i7 Jߠ@ɹ t GI uܸzv]ѶSz<O"?ANc]>AkXۙ}F66N&=9cs<[v`iH!/**AHك~æ՜29s ػo>m4}ܸz[X:ѶS:H~!.1ޭ;45[YQ+(.ʧcAvyWHKHMnӢU]899ӾK_:tP^hEB]$>:CCtuΩ~.~Ciٶz;{qn"wjN~qhE#]:InN&n>~F&%%EݻԤocj 'O!%.;ȀӉ $" 98`٘Ar!.ͬ3x"Ds-414瀱F^'+3is^WG%.:|\<7d2NUuELd0F=Ξ-+Ғc(kT %ѼE[ec8BQɆ_?Ήaf/ @CD[Gvo C#S&z[ݷqmÐO```tsF&8xqll47odY=뉍Na~.<g7oq¯_z4%q6>C&a?'3=֭WO_ U鋖6͛C'aeHiiwEb\8x1ptYrlzRwoy-mZid\x+hhӪm Hfz2'n&!6Sf:Ucd'q6#e;'7z54Z,,gX< 2SHK #5|z HKٻa9o17y Oܼ#ۈyYOjwlsJhޢ ?kOճ˔Ӟ G|%sЭ(w"';'\rG3u0bz~=3m8/~w>Vx}}#} ~n1kPT7tFθ'ޟOnv&N^\r3GEY!eB;ckʵS>>'s?5?1nEs>o^c~T?̐1Tx^:,ٻE}}C.t=VakBIqNӯ} @FZ+>{p0c\<+o*%)6Ǎs887' 8ɻ_lDWOWiF&yc?W[2`42*|4E{fH g`fnIYiJ/^%"4sKk]<9stf ̨A\80"C" ,J9b'i)8:{å |KȔHcPz? ϖ6n6 1dJvȲ9(*+T(]&2RptĜ[Np/{$tsem:ڞJHyL,qmÅS{8{|'3~}Fߖ/!aL,pti>ֱ뒞W'/''Wo$mkOqN}k|t!.&<D߼=GJyY7w$R׈ =? 2Tɏ^!-9pO&6*geU@rB4Wqt"1&O#=5 G։Wrq|=de͇O'w3Gw0奴ܷdYNRz&ɲ\D}! Iz =V~°s;dޭ;|Dl%"$ރ'g#3=g^nG?āMxx׀qƳuW[ʻ?`ݛ?5y,1s7ԛbV}6j>e;pv]16La7?{nG0oPTϪsvF`ʏwbmLEE9_?'.~JV}&`ȘYL>Ydn-<_>fצs&ڵo4s]= rYbNފozMLD0V}/^|<Ahfpǜxa?!6c'HZxG{/<ҧ7‚\>[QVVo">&is1lܓfg͇pYb"iޢmqX֏t?Gpz?}M 1&oû->]ذ=[}xx(߿Cz3:v@Vf sw΍+ dԤ= IIf'ϱh٦P\T;_lDj,9<<\]Ω[9gc>~*vl]~b̗M}ѳ `Oyy~,{k: E$.;_߳e~Ck8fD|l8gLƦd'/ϯiݮػu%T?"f͸~,?.{\<$zi)~Jk-M¢VŻH /7 36n6qX:Y/3dy<5_gȞ$F3煏3x"Y),{g.珐u9%1w؄[ ¯_b;sٻuzgGcniöeU\>{S򹃤$4r~N${DKŒ$g?DuЯ:uLYY)oGt;Hee]zUw$@3k;YpХ05ȉ01DDh۩7{ZKeu!IS|Ue:oӱ}O$7;ilp0F&LXe022屹ك򭷰 cfam!eҬW5i>AB>s 6Sg[ vCAȾF#\>c3jN&L:\:s3tܓXU)7::L2'/@O견*%nyRx@,ZH-*ߒԤսSMApjoZ$ o8NAKKSf<6wq/">:6zӥ02txhHQk3z|l\sܱZ0f3`mL^H©!nfaʹcVbҦc/hzq<6:ٙt>ş4ĂisamDnIN"a]1q K}vaʓ 8ТuG**Rwgo4NUc6]stox-mh@5jbLU,O|r>Bh`,q#$I:bU7`';z ǮM?r FM,+?GZK4nV6XZٓdn޸̷=VWK[̴$JKIMQ2>.-6ab 7uy:szr6 9 K+;_jrR-yӧ=~EhikݾQׅJơʢR{N,R'lLSrNw|-ZuR &tEhkqs25k\mldd|(VʇkqQO!51(HSʣPkoU"`bT5wGOB/_IM%)1ԪJqeG'Ͱsp#3- P>dJK01?WHgVcm{)ǜ\ w%1.96%ҕg&e$)>BuݍLqr}&'D -WW> }W}RcspEK#|V: ٻGӎVzбZ\W{JNBTtdVݣh r9st;I$FEF^}Oƺc#st}J9TJrVNʅiOiߥfV O Y$i,}h$IρC#:tc;  ?HM3Ȥvj&]==JT ksl LnN&EUc68V=B[㭾QQQV\EE9E;iOOO|y9FMKdwR\T9b7[~w.6X礯|8TמSyy)Eyh~`S\|D5bc7xvļvF&ftޅ&V*F&6oI.}LOh᪶hU#ݑ颼^%8;^cODU NE~@u_jjjI}7T獌Mjm,:mC***4(YXTLԬ}U9aD=VzU،vbdlJyYjX۠o؈ԜW_ə fH !Aس&|!cf۾UJ-mhFe p5?}H~-MphMCHИ[HEGG΀+G^yNJKDϞ+3FOYPHd lh<=I˲|4>!:z]:Iaa.zz3V,u3lee9Y*K#Ϧu7lLP&,+ȸa''+H\od+|vѥ=Yʲ ,U(18 wy(st> šg۟0{3Egem,l~u@Oπf*SxMJr3U~VȲH[wVmxh]URy|ZkOl[x{ScXg3ŏ{JXûTV]ľsIz͸/`[r{BϲgVFWUY[_+++FQP4)UU5A Բ$'DSR|n3dj r70wٹO9/ڹR*T/3.dkhY[m]&X(SٺVTU_cWN<̻jJ FOYV~է WsJ)q+2C{S !31 gFj"g/WѯOP'0- (o28&IRI(ILx(w,gwB/r<-NE$(ZXxT/]>X^bM?7^WH9HnbU7o\R+_xmmsne(0n+9|2+>`9~`]XqQ* $I{`bb!Y4]pO{C#jt,^ӯޭI-l7CIӪfox>;N-HN&WR} {Gwz]+].ϯhѺS3Kl\ eV8 IDATiۮxܭKuΖ#{" uv#{8UJ;M,y~4]{ #9>`^$-FL˟?ȲwнHhKh.ڋ'=SEe%K^!|wńEt;ہ1&@Ov^ޥu$GplFYIENt3s'v7 3K.Cr|~ǫu1j|V~o>|}FҢU'npVmSgX9senۡ'VJkEls<}ӣom5(cųoN^]>SxH!TVT`̖+WZDjb 'm!eҡ`HɍȰ]e?Ì?#q4 ;Xj+0큿%IZW+hMW[wfH 7.ӡ@ܪ ˞+161WEh݉_\zU߼>>*6Ͽ/1՞>fVL||!#&Vf<oK `FUYQ g˟_RQ^NaEz5ߖ읚›lCWڻ`wۯ~Zv`EXX٪kMzt`Ш;_S//̴DJꝓB~l ՜ ƴר>'GW/^XMdhdWˎzZ~c3Z$idoէ{Q4~ 6wCV(uѫi=ӽHneph6^Oy̴z2Xktu"Ix` ZW*нJ Y[,ۭlbHM{Gwe%=5w zw_0{87o\ +:(%5pl]ryyqvʖjEwԤB 9EٺVJ*104@CfZ"^:T|70 |L怜AzJ"Ϊh**D^n)yo@ee:ȲK>[6OPr3spXscâ 65ĒfLb^1=${aP{g².>̝ffws=}~/\jI .=t5WBLyxyahhDiI$i?eTTcffPUUW+TVVJtU*++qv,p3Rup҉ƬMJR yYxt<룸0ՋVǪJ"ږ ]$6:98vtvޖSZRDtd0Uxt퉹;chhv6( S3s ku w#"1r/).$uJKKp|P^^ʗ>ʨIs?trLX%>y2!}5-*Hd?Yk(C5#!DD Cznͫ?5M \z߾{gǎz( г~;M-?c׌{~ ~Em칯d"Q6>^#hc$IR*#hP$i-2oϮBsMϐGR|OxnxE _]>ŻŽ;D]ëS~E1447fSPh .K4v椠bU9s]UB.$źWPPPPPPOb-=+& B !fQz4?K N =B) UB:Jzd'y#y#&j 1Q!Ds;{QX%:;>^Fj"7(+]pB-ob\o}"8~pWC%BEdX EtRb%(//!F-wSHK[}vL$͓$@>M$uDBFoB!eSGsdZ>zm!7wq>zm!qG7yw"&2זNa/۷rmKؾv9/7i{k it?~?/o~;boW)-)bOX{}JK쭇ٶfyV+3~7ޭ?k u1a|B[[G- bY)U)hx B$ ^((+9uh 98Vh=˻>.'nƲ 3}6ֶ$Dtn=7}6 YQ7M>@V~c({eTg[HN/- r144b=amӴqKPEaA.V'.@̭gGd *I3HZ !nK_ZEp)s(/+aگ U;NȹS{HM-]{2r:nr #B[7LORG#-)g 7GoӇʔ9rlzðJ7֊tWN1|ݜ8||gDܸ%?HOMvxyc蘻ubWpIػ-Z3gڌIN7/M]E+YC+NdX 3}P'5pz?1!fcޙacgҹ:U*l Lpf:I!o\;˕GLK=z );!:2`ܻdd"6:'m!;3G 5j5_G#%)(߼Τ&:2!HK`ݏPTX@iI\̺2.:yxpB¡C' WF?Hs&,"!$Gڅg6$Gqlz2ӓqʠpң6B$,"YصwπxS7$ /E6t1w!I޾ʊٵ;JQaWbՓSl޵_' !67Ex%$c3Ρݿ}r*++ŗ4"?> %DSTJ"62mi"_fLO֭ٝػ$b_JJR 9Yi$%ޤJv^(/c'rgsM;gXGZ놟GgwRbpf?q7xOJl/Qa9 <{d܇8&|TyY|ޣTTT`׾#9w|7?} ,AWN1{32fUNQ3HK$>&Lgn6!ک>#-B|FPQQ@Xݛgqv>"#'sϹFPxFUe%]{r~As]RR>BQa>N 8㻙uJUxGWl:x(me5uOĺG6mqrz?O%.:KtJ <Ô9ghhDJB4Ne,IKM=B8g `ddLhCz ŃD@A"9>ܬtU|vm}VՓȰNNXE=9ݿ(ªkfZb> -FB$j y3ĸH!'nqtS?o g<w@_?ص[]*T?ҥ{_>lL}~bo{('>J(wWG|t(kG ;-9Vm161!.;֯>>!`8w-^5q.o~>Ah^`5fիO>o$I"v_cƢb_p`{E{W~u1po=îM;?i]UY_љ$|1.>=ڶ=a!سG:uKɵ BX;:n^wQdeh /&3g3:8q6|G/Q:ڧt6T pvׯ1f򽌛= QŜbieC^N&+>?ރs({/ K&=8֯ZCW,y/~IImuݏ{N\8go;h &&:mvo3 7E!yݷ>'taK_aemKYY1^[ĉ6V(^$$Пs2czӟA rWq{WO=6Qeśc3}7x?:}ZfKǝӣdN]O˸k&yKgAJ:g uB9ɍ# 24xf{ 3?vfǺ WSäYY$ҹzҒBB0l2޽ɽ;N>b knxØrzǼr7ӽ` 3h,=}ԄzGܸ[WY>0kSt9H0r\w» P_mmTV3ht\T_/dcwaEصwOon,Zůba7d 7|&fL&-O 7`dsH~n&&˻Z[1yFĔ{S'@LNZJrvѯQc(ZʧGAEXƦNOMD'.\9wxR*m'Y=K+>,+=-}JU> 3HVV#+og$;LO}$B.VВQ6+=\v./7 (;J##5!uV2;8m}2ӒZGv鄬2[{}h iS'y +=5GIqIfĀH__Q5<84ae紟sZzN;xvEb9j5tpVy('#-wO_ΞnV=5)CCt#w |՞Q\:sBLLLqyyyEDu#H4W~~ ~'WOܺڷBfzd%?rNmTֹ LEӣ¸3 &fTVT_\9f溚#cPQC~^[ΡŃ{vQs73UCEk )+]-ޑed N^P:Oߵ98w8)uS⩪l`gz WQQ&1-yvq+q}Q3 Uwd%QYY255Ƿp,-u0QϹ\126Bf'/7m$ablFi8?/FͥS#-}֨ ^=FZrQattBqtvfU2ӓ ƻ 0Eya`=ڣu4Uk1$<0Y݂PJ!Dˇ Uے)[ee$S\6 Fzj;t@ uH[k;stسy%VvY.<§\<=_?Wcdd܋ HOѩvuJ®#*SM6mwnֶ2 3+*̢޹wt킡y9:ΟKNVCjphמx|}٣,I%HIEUU%N^y$C*+*(-)rK-Zc΁g\);WUYIII!-vlsvtr 3=ε9K i|R)*̓LQG2}jgK+3tΩ®Zh֎bҒpF%r~0BZPYve[:8{vڌ1El3]ۤU>MVt4/,.it_(_.,Z$\;wg{7mNЮߨ(@38k5̚0d N/!{ IDAT+^qd%pL,ꍿ3g3^;ϡݿ7w}n|C\t?lRXS8{ Iq:NBeECԯmS?^çbieÅSHbitpVD[Qk"NJJb4g>ȴ{Y2I8r/L1f4!.9-?dr&zs k+1q"&!~%E2e#G.9mk";3JIEyM,OߐtHLTN6vvk&} e;<FdhOm4CC6M8qp7#1f|§}u&|Drxuac!OcUxWy gc'/ ̂֞)}^!^=l'ƦT4k0FFƤ3|ܜ&C'  :M+0l2f=%Cѡ4#7U1I$=ovdUZC1%s5B 5E1(؄/}U5ܹ#c\ܼX[tY+p6 CW|}V;BJѺ5<_Ⱥ>e4s 5s'q^ZjC߁x4?Κ+u"šZk߰珹z+hk}%}TU^/| Z[Zq61~.~ESHNFc\bܴ K ٹ~%[3鮇yZcRYպ5O^ƕs5.;_LWU-). 3-J>\ tu;~[*L,vϣ̘ސ13yww`ddp{ b֟tվΚkSi{.uݷ4;Z9ĻTT!$ &q?gyhR gTUUblbʄ3{Qmt`XJ9jժ zdcoFm&611牗`Oco4{A{e,,jا0ɩ#ܷi^~INXU9ѵ 7oн@Y}U=ꖛ[0`d.doeyo'\>{ջE;豷3pl>og=p'_Ityp–3!Dz$X-0Z*˨(ܢ5D^m{g?JJK015>3 ɵ lz3&y9BYR\Lݕ+vuf5ܽzSYYAyY)fjPr3y+:{cj&_ PUUTVVJt5*+*pv2i# 5)C#ۻhvm (NXc(//B++)//{=9YiEbR> #ccYRsWQGIq!YDJb4]B).?/ب\:um;{ͼ-Z!I!().S| !HN"=%vv8yvsqekJ 000>@iI6deI.M_ eTVV`nZ6$;#OoH&16[8xj(--F5|έdn~^8:u}63R uk+\ݽeT*JK166iԦ?c6}ꞯH-Dг(Yp%I>nήD[믞?'c jζiغK#jB$˻ {a$e6ёAУȘ'^JxDBu* *{@AqpD1kd  KubPR\HhFϲO_!Dℑ$I+B=SYQdUcLKAAAA5 5%eŜ=Q"&'R!D-!D1 `o)/_AAAAAAGЕS_8WOV$zy(NЮ(((((((*U[pJ-ZJxR_t {!2Ng{J"C)((((((.ĸ ƴ@h=S$I2N,gw No߮9|NeC[48aS$;7 N"K@G{Gy;Wg2VPPPPPPgp~ !UIG[*"=t<%zfuqi=1he/~wj#mkbvMh!D3ߖ#I<,u"N]'(И7Bs͞\=Ht600`ܴEL{ Z[P -@LdVJ5E)XB6RnPkPkxOm9B=MWcVsmF[X2q 1[-=BB YPQo !ל>%{n$IV!=UdB$I5 !n$ICw)wEcp䅕mmܬp"?7 R @SgkW;t \+z6w7s!XIQ_}<`s;$nS4PM#HdvzmFK/-$fc=p2+(((((()0`/WrlY7~4OsmxBQ-WOYo$ߍ$i|sPKP!BF5c:? !ԩXP^1Q_tEIsjBV&SZ:"ݸ{_jJK8Wb2`bmc,55$I_9ݭ:g]N!tj3CTk^H|u5IT'J;e>zÆܒj2'IՄ@fcJdD4Gq&5T:m@SB1 IP qfd-_G>W> Oo}ydS)).xWέ4'(B(`"jO}[ e#C 0%jF}ͥ3e@TU#)(y\fxڻҒ"!~ 7L2ӓX[+ݶ"[/*UYi |͎o3xY=Tji[XY1i5Wҋ$I6$o=BQ>^F[<)|`̫I~`Ԥyط6L9\tB\۱LA_KDe<ݿU< mdeBΟ@S74H} JհvuR/TEBl8 &ܿ݌ x&#$p[P/iTk*SKX $ɀ)CC $~׬L<#?126pMՋǹxYC'1z{D$bB8yx׆tS2b͚-|Q_qQ>!^8JX%Mѝ̞,6o=דcS3fͱ.̼UY,~Lsli՜ LL?~6 wP}#!?cbq@mʹòU{'7Rc"C sHK$I(*̣m[;ڶXZhꕕp$BR [KjR .H:tG!Dp3"HS7._=CRl)Xs{_nay0Rc)/+;yѣ[14s @2ӓH\::Ia~.Fƌ2!!a蘻pUBjJ,y9sOo?,esnq{NDGyk4b=צ ē@V88ҹcc\uMO=g@7`5puM; /GT5RoRTT@[k{<ҽgÿٙ^ӮJUE =UlegD~o>~6w$ajf΅_vOc, JSƪ;#sV022f{w:bʊپvJ\ ;p s=cS_Wc;eYucm#24v7~DS֣0b;%E:c:81kS >UV̦_?7$6򉎏ę#;xc8Ö>#1NןȘ2뾧0֏]KJb4ΝtГ%;7G9~`LHҗĔ?Q@Y؛)K=}xzqho}iI03V,4&]9%sdvA[k{"8sĔѓY.5_j~ymI2 ?䛚PO?|c 3 @ lpqZ=z wo˧LuSn;z$i)q}7hf;C~㯟pl@~^{u_kz /p#No۶JGȾu:UV^UUo/uP]>wU_wGxJٻn\ӽ&m6F;.az̴$~U5Da2Na!ت%y>3Sٰc r=vc3pLc|INTU&TYlcŐ@T:+r`/l^YIdo}BwBО6kCˎ} ڎ>5e 1ad's`mlJvL0 wFK}`ϤdjcW;7'Cf3NrBF&xLc13?.L[GVݙ2&|@vm\I}$'Аn2zTYY!33ե0?6=wlBjsb^4hPqt:kC됒MUU%N]{$-&7+Vvu]&͓=ph9#.g9tdʜ%uMk-ݛVRB/T!TD=z є%5&MgO64=%EXChoh%ɠy?ڈ%q..Ԕ^GkFZ r4OOopTo_:kʌMLw+^4F .<{m뗩J z<֡#᤽(jg߁s'ۘöˢ<:Ye]10vɭY+{f MC+.UAь$I*\iw|V.V7yOA?ekYmf=TcBxl% (ӖMKF}{:8ӥ{BAcI ùǷ0Mޭ?}ZkVVV߳5>*++͇4&!T$Prj 7FW,%7;c72ll_"Cld}5\3@p=lkoߒ}[<8v M?\Jecc W/C.SQ^4llfJs~~VPvM&)4F =). \?HnNاl췄k8ux e3~2_#88}=B|J#Djb;V]u4Nk< WVeQK+bɽ,rv 5ja\Z#6Cikcc䄹̘TVt^6'w-$Gp3<!CgwY<##c մ%1M IDAT5Kv̚_2j\\OTh`=T#ROxtYe/%<" ߪ(OslffE6V-5BO~n69:N@VX߷̼O^~k2y/o?SQ0nG!ؿV zKL,<P/njk<ܣУRUW/HvRYYAC3Qi-bi1;_ّPZkOȎ}:[٨M\5ڞ䄛WNOطwј2ӓٷ'm xvgw? 6pTvmNs|)sWFZ/e>|]{ujGիL0rWw׫X q=P9A Nyf|~ucƀzEѵFN'3-QCW/aȦNꌚ)*2k㑺yxFw_=m.}jgU ) ={6Otó{_tKߚq F. w+*'-9N쫼Em& <̼5Y"s]zmmx]d 5x]vr[o‚lVڈ+|hRv}eg[r:eYG7ttBbnꀑwCGPZ$fVnڧK>ؽ;d%cjxu,Or e[mBCZzi46t4W)/׍ͲyW+zJ pZ74'.xt[שM]3ğM}ٺR Lm`dlUZV^Q܁~a{0ll$i#tRE»t|̚JPiJը2L_ ]56|5q+:]!ׯʲƷϢ%~Cj}:tV<1}XDzʼn?6sIBt~RbX<§rg c$K"#5 tV.fL g>HVz2W/ 4k~F s-D^W> =|w돚ٓ{;mCܜtN&+gT3uk\| Xjg$ڹd >k Ѥ1ML7m!-$;+kOp9uܧjӘ*_==wż iɱDܨu[wUZVZ, pZ#l[.nna=@;rcG\t(~o'1.Bַ>}qzrXEJAǶ`,6JzCW}Dtvyk?E;#If34!DR|;lҿ>l4BOLd!g{ι{괩5ڤ%ǑpGgwMe1e,1{;0n"M[D+|bQo_AAD,ld&<OI1\8_sՋs7}LL͙KشkϨI5i 7Y" qPmkEQh  9ynVF ?1E 8CYY)fder^M]+k;FMS3 TUUDQe'X0Z#$rMgO]'٭+=z%:~HJb4WOPUU}4g߂%abw"F{0hĔ\B;lv@M}.>W֮jYb˚1~,sZd&xxml3d LL̨$:2Xu{1 ^8&3˚maVh%E$'Fڹۭ+k1`$v[AQa.ee% V6WӳNP/Nˆ(Y)˚)-[TkrYZY3v|-,Q @sޱfN[#+\#I~Bw PO n}4sӹr0GN .ڧLl^)7} ٙFFƚ@7 GWYTh]y TVV ՜PԪ/#sh{Рs\>wDZG&Zbc>s'MHKdK0_Ș !]ݻwx׀+$!!B ]bEb~" J%@'{;,P}tKwӻ0#*-~'%y:D&:V.p -A;2es3 X' >F| f(8=/_µϾyO=U'O6AKn$'#wSY^Bcc=KȎ 1!#5^G1v͞z}׭-e:3~ ƜGW<)uu=zwhkLR5rJLQx$Iً\F244b!@>Nܕĵ{z.6Y/ON9F>M^"ӯ-cM;Ggz[g8z@WNn2h}48+uPR]S^ZBa u؈I'jm"6c۪7?GA^&&l͘Iw׌ ;C{֓tP( u;7ާG$`:2,]sE!I:'wZCScy9`ay~y9i=w<_CuEM n(.ͻ["ebcE;QϗƆz 3qprdtKUeflۏg$8dYEa^fX۴IMu5Ue,llۍ.8b;4ȲA"I+gdK+@vn=dYfUĔ#.{]וCC#\}ͦ/&4.% =$IqA ,,mcM#czx/N ,tAgea-@ p @bYiV C놿!Ze=U/͜|#(y_'ڦlg"ܬd o>5WgMYx,!)J˞ԳQGLN8'&o捧nbw_P;s?~^Qpof?1{_𱲬b:y>;x~b\vO_ުI/!Ha~V7Jue$i$Iv-3w=Fhhˊ*ԩ,TS_WMqaRɯ % jn[o?C;ptvgi s;Fݾ}/%\v8/yKz^es3466ȔS[SuATQYQ (bP)cIt.5E'Kknn h"MNUQ+C``݂B`MHҕ3!{:CǟŠgˠ7hʲ?kf\-O@\;GON8Erikpqwpl:=WFjXXXNf{ Ԝ7;rHM?0woq%Ey$'O@M~SS&?73s 39oҚ~F؎FԤ(Rĭ/HwrNEIaֶx|\ ME!=9cSS*;I >9##Bˆ>y$<|;zL-()%A*ʋ !tcSIaۈ=AZJ,Nn 23 .)ځ Д LmmMMڻQ;}t/ֶtN{gH't$#rjk<|"Q'}3}VZё4773: cRI 044ɝ#&jƅ,8o3nz$ qptlnp;CWfs\=8 Mya~gO't8Iq))#dH<}5ϱ( ݽ6R$Je@]u}&/bmcϰѷoptѡ߿d߶?QS_WK`< @B12UYP_Wn=]KRq[ՕĞ7vxMSa?:dFsS#F$ŝ`ڬpt63[,^s}^x=גQ*c?2dMD'í/ɱ:MniKnV*}(=Ź,OIhnnbۙۘcR^MYPWW<#NľMo [W~kqq#/ޠSskۼPjYtFYڼYVabjF}]-.x=3104׾T~Ass+6G!c9oϽ#v.$DeقyuԤ(~&wN^dg$#% FF&TJ$IbwkU}E/6JφUPHR_Ka(͚1؟? <5 ?|<eŘP_P0f=<;KIO#?7]sNccnL}P$-}ғc115G܄R̐Q72}XZ63H T*%A!Ce,U-JwpVvmZNJiw%uanX mbq-TMhnj؄[yw>~Nue}1?h~/ -+!aL@Bdo{"7+ڳAsflk۳w|G456R&#)*"#5^#k_z<}㶩9?M|MP)8yo۟Y> ,.L&}c;ػY9>湷~%?u>5˿˷7Ͽ=9Ù=E_?%T7M}~g39g=[Zjظ'<{7üO($6FFG P67ܛ?r~ܴ$k~n:|5KK_qɱܴ#臍]z^ʲbcO1W026Կmm~'^h1sgMsxߦ VTJ%|$L{~׿f7cRnܾq17,yay,[xo~Y}A!ag%qg_9*JYիT؋|9ή^l\=Ԥhf1y٩;s6sE;n]Dsu<Z^d1YK߁בs?Š7᜵BmJfͱxnIZO=|DA^FP]Uo?MMM=2䳟ƚes9s<@@;L}v[GE2=|^nI⢎uf̓O7g>Dl>q[> Ϯ-+HQ;dt '5)wNlyy|`co4vn>gb'$DG2zݼ_|:o ή^dv\;s>ՃY/~#x7 IDATxY:ܿɌ'ci\Cܙp Zf^]I(dY~Q XH# v6/Ԥ(}&&<zi"aiec/~F@@5Ezkzϓ;acȴҖ][w݈*]W`bj dH 16;P_ Kk|bhhwޚ0JOdis & xEY Bri'nS3lx؏C{7RTiSe> }Ϡud7qQ 쌳:2<)Ӟš7˔iRVR}۽[VPT͐Q71񶇰Փ{~I!c㒖;h>l]N=;6g-619 @ԉĞй}17ދp(.̡8?bm|,V cMӨ(+b:e7SUv@p k[L{~>;\[W0)TWӋV5ԫg7S6صet'}'C1uC詓ƎKX#^G0BBG0;( %_a~6{Y٦ڎ}%gsNKT+=9g=v~n,=2S3K鷁&`na}cfnpųL,y᝟ظj>1ػu{ѕ[>IhTamc{fuqaەŔئ|}IṞ6d&wھ, _%EyZy016Ա=9Ω=]>аx}PT2S,oqhSfnUZam12rmwzGw< K̬(+)hWB$IT+g[o\kEŹb##6}:޺z2Isa:,Ák,/Ayv{2o00@zZ3FڻV(-Im*_I ׾f$'&94/@{ W ,7 %I ʲ|%ֶ'tZW0sIḴpN;w~Ğ:DueZ: >"3- K+G·P\CȀks5n{ ~KGM~^<~snJ4|I6v|#T*%1's"vqO'lvSs99ғc8},Gvrdl휸g;x{\4eeqWSGs*c|CSQ[X»II8/sbo_;:Tm~ћehmB?L^lJh^SJTbg a]'q}Oq}OO}8caecwA̭K_P/E<-2j[RmhW鼀K ٭*+ps'M7@uo>Wvn\ʖ5=gD@{sg;/J'GbE;W[]q&XZcimˇs]Eh:x PUQD<Ƚ,>rEN \ܧ[9hjҝJݸz>9c)*wb!q3|C 6Cb ݼ}Ε[$FBCC=-r?~A?kjf'mY'߯1tKyI!gNK3661FAvmM=/2 z}tNEקc =ϴYoq3lhJ s❇u|Zg?Ba`@vѽ:۾_142&l|CFJI֖#&游y3b 6m $ f./j@NnDo7uYzq [SMsjRU0XZِxZ]~7pf*JGXk-{Ș Nɏػ?K5^5I1cPEbq ]_89 YV鸟k,:_^Zgo`ׯhƻU'<$kHUuGr$Ʃs?EQ{hꊞ%)V޹!7dG8GˆU/_g|T sgĩ<Qێe^е\\[1TL,}f0W::ZֵN@@\zP]U}صyUephzT*%~| ?_ю]MS!4l4# 7igH;d'q݄;5kʸ͑[hjld.֮KfZ"-I=KvwN{AXXy`+'좺ױ}b&g0GmE@yI!/ѓvmZΉ#hnn"=%4P{>E8Օ޿]SUYFIa.wGTx#j7]S]QƎKٶNspr'#%-k~!T*$DGbdl&L+<V6vlk!Dp AqaRcߊO/ 9{QTc~]y$|Y6 XSbNZݗd6GeE qQGX˧(b\) = ˜CCC=md_ J?(+{j9zpNey %oFJ^4vҽygJNٍJ$voY)CFqЗױs2멪(eHOaĘՀ~mg_qowӰu䟵q6$vY@ K[j*8YcMPHM̱}{jk*a9GѧZuđPOľlg6]ahd1pEs +-,z6e%;n4wٿo=K^cVdגoHO/,f?*I$Izj) Ue{1{WfAx7{Bb}bM=cc3f>!-ksRTLsS# cp 2ٰ'F -|o8Uܳ5cΑqLM~=?e%M2Դ{:ZdYp܂??Kk[+1fïiz%g察a<Q*n<7~yגoذ'wpeKcn}{GWz}V%kW|ϖ5؀,˄ĝW/'`w3px}6;s6uls!;6.C$M'^.L!bOfeٿYd؜?:D‰;Q67N>NO#&2esl]ϟc36a|cqvG܂ښ*\=t Euf%VYn,_U^K0nbI=NiI!?cSs Gv0P }xj*steȉXZԩmbjf]coaODY wt*k*6dGEy1'P\$I;1x.=Z9uښ*ӓcHIx<cjm r3=AMu90{9'IN8$I /GnɥJ䥣l &6dm"b}U;Y 7(8t<ֶo\]k]:NE /Nك!JEl֑Z1$gwC 2ke$rBOXImI=JSC= ̉p6soȀ{̩ғ15W0\zu^:44q 3Q({0`6EŅD:1>(ń;LIzp;VֶyZ9qxmYcnaM߁QVOIq>î ٸ8LR J '8t=5E٤77#', ;tXQ/vnZ_ey~$I@YW!$I@sݫ%2XSy[Kƾ\Ir2y]WBXvLrg.7ZNPȕ#Xl߰`,m D[,W r= ۂQ*Ie/w( @l&/;E]Ȳ$yE jH:A%q52l8ydWwqE```ӳjE0Iqej7Wb v I |kͦW-}a; .?J HO:$r,>҅Z]IH4ثP0g.Cy @ صy9@)w($IZ Io{qU*%ݲ@ Q)ڑw:N-Xwb !qu-\ 5t,@ j+YR A;?P %}VυTUzIuYж$eˆkI Pk0t׍166`@ 9%Ey͎K).i.CmóbڼjwY?$I Cmvؔ釽 q͈ @p$2J)-'94Uhp +=H4xXv8@ ԤodYnHd J-^Q+?>[˟U7%Վ (Z,GkJ@ VG.z}L JsY@pmqM'@p"&~DU6>$ iɲZ!IzVe9I<-ȲH逓VAYk{w,J:~ZQ,*kc,eZuFeY^'zmUhRY`[hK$?VfYknC+,ˇʝz,rV@Vy,[cr#}Q;R)ozm<ke˲|J},sڸ3C+dY*BdYԪ3U"&r96e9[`@{"YW: !rVy/`Vy,ڸF+GdY>U ܧ'|YjɲCx\,i ig˲Ϣq ج{GUĐ}ȲYϧkZ$xޓsH &]JHXJ~֬C,vu5(<[<:YF+@ .ɈN*%@0RΎ 4|:aS[$@ @IN Ƿ|Nc})`,˵տ&-r%I<BO$ UJg`p@Qz'-2Ge@l fїw}̡?ߠc$#p:rs=[;Ny~ʦzlqꇋj"3fեYTg 0t7E}gEMvk0rPqcB'<),$=jr-EV01 w ԭ.˦$'\se,מC01 ى]{p@aqjMUXysf6$'FS^~R~F6Ask|MĜ#f@prX{?B J=Scbn㊥Vvع3,Ghߊstg4k6 47Q@Fl$+vn~3'P"WS~Hf=Xw453N!pXcI~è, ;~@=WaT䑓uyMEe8s}"/ff( Ӛq *=v- Ӽ/Q3in(N,ԔQSGzdz8z O# N^%(BSL$IiyVk)rF& c3k=C*NH!X[U ȘbbnݐsOzya2yZވsݣto{,ZRn; F&XGVeYC|L-$n\Juw!U0Wv<=b3cRU~URo>wq-jŨvYy{Č6æ|tG!) h8'Ho?B4{k>YZԔP]kQx$R~;6^^:(QuXȧ"­I4m׬C34l+l+ ]lMɚnm0,qC츶K-Y%RxI/d5=@}ޗxX|vC' ]>ޥ$D'w{5o+[%5`f]1z|KqHNY`^LPZݏ$!"()(6ܦ=Il_0^M]4iTk+w.|poަwKt}IuLcPp t ے># @oF-1|WǮ uN(kU #&zjo\*B&2s֔F0UMCAfǻbzM)23@1E">u{%5UU] ]':Nsv?Vg`\3?U⍢P0s*&+;dZ@pP'g0/\{cU5:'%G .- \ Ysx21mPe`\2q4LSU6FoX^ؘ(]Hek(K~Q͜U;AJɾ_XZN0`%6R.މ( giSU=Iߒ$QA*3}fFu9m\?"zV^^NxtNk$2oO:"IaDoQq.oJ`T%e\TDc+y)nز\jlHRIӓP_Fɽ>S)6$*i!\ ͌vޢ*F0M x+L#i*>օiIY>vbA'ovzҋ =_ K?% zjt?'9+*oji? ZJ8ur &=θ~_=jyUj05pCdmj-v)'\ٚ` ,uP JkZ0$2S%KRX'H >ٶ6NSyZG5`ۇny2I2'+-2 y/9mIFύ\bۡDիbnR 7 /MkXZDTXjZ(k /ވ!+!>UFk`SY.ܰ[O͎13=|o+3&*&KU3EM̎;"#,x 8EcDunJ*1h"EUkp 1peO3xC4TlWǟzCL_d wIMqՊ9=n9hz\3M+imD,TT%ɓWPҀ9Rēs3doC531HIPWXi8=tÀޤi,uT_<_%[OF/g(?=x/< yߗY:̍ٴKJt3x]Stה競OFv,LRqȡ /ϼH׹x1b Ҵ!t 3(0I(/kE[QWo{]~-7e㎇>(c\?bڵCOqo+9A~Y*v!e\Ai:USKսIsFu|5;I$P Uwzs/sʧ%~/yvt߿KVvW XǷJ2zM Y=~W#[ k4AgXgHc+Q)%]_H2\+yߟg`T~q -}JSM䧰Ku˲ о/Q܎1t,rXvRPR;?8Š gGplk]+mfpcәfL֘7knccr\3\ ""rL +r?b5:'9)9Feuo.{}x]S,x d 1cݸ8xl#W89̞cUa{)ό2^r;Fqbyc *-ύ[VPROMV ˱upFʲ9$cA|v^ZIel|6'ZbnG3r>k G7xO!.OLIygηFYUSNO=so^@ X ro KЍސGS$ji@1TUQ*.| w<ϥ2x`=,H$𣱞mX6/L4 { 7 ,b*NPL| ozxv>ΐJ <\?G);@%Ij}UB%6"5@pw,|L]DY9LQ^T9zrXt2켒U%  މDs.uiDxS#˶֊FW%uj۸Z]-|ٱN{⛟#di4Qq S .\d9Dv~)|+͟OۓM @ w4,_ ѓIt)B$@Q2LD~_'dYv&7&䐮\IENDB`stxxl-1.3.1/images/layer_diagram_small.png0000644000175000017500000014041011437146445020466 0ustar andreasandreasPNG  IHDR^"sBIT|d pHYsL-xtEXtSoftwarewww.inkscape.org< IDATxu|Uƺ;Xƨ" (bb`DQl D@DB$5jcݽ8?vH =_?~8;9y}AE3 }^2(jDQT\eL.jǀS Q\uxA3QdrmG7 OBB?FUKya %TV l(jE1JۥaL&_%W pL&ok$$$$Z Z9su}mE<&iwWgO-߿z^Xpq~Q2rGXg["q TP ] 3K9IӥC=EMUi6vLܶ#'~0,Vۓu>"Ve(=ONQL\p @Րxw 3.#p|ŒHcQc g~X{pj+]ϣ4/PL,qo+6RNR] 6Ν \ak)ʌکd'Fjp{[PW]BN1 PSQKg:n_LV`dfK>3+(j +%5EFը0t¯t 3(Π(3ZUCQV yTeEŘZPSYHQV UeUӸPOMyF=ݪ UetԶ%f2ʒ,RNmS =vg|˗+jf%^OT* SPVzVKmu EY1h529UeFSK"2j t߭49q7Q_)ɍGdȕ$r/ݏoȴ75ظtF?4)ĭ Hfѣ1ut֐+3MؒڪRN5+S[YD ?: ӷQ^LIa䥜D&WelF>")g}>W~l,F&S[YDIy wy0U(F-*ʌ&#v/>kB&WRMzfj63gy'̽$7w.dc2.~ Dtb 202WJ'n#J)=* {RQN^ ~_ݻ¡cO})ʎ2J?!3͖ .EqNfkSZ:!"%ph5jԪZrQV{Z+QbhlI#+yy'(Ή8'Acm]1p SIa LV!8y%яB&~2f֮/Mڋ2vn3r""2d'\бOmGZߔ ,&X{SMIR5۸L>gM9``lL@Q_TWtA&st8'F /lʕL\9ԨTM_lmAeIEUkZkA/3h5*ҢnQ"7x [YKgJnUiEdf '7gC8x$:rWX{ǮY6lUe{x42ijDOzpj* :5!( =X-ۋ=U]otn RQG8 -y%!/$ǛNgZ7g3l(Qbb]S+gsʋR16( =t,%Sۉ,4:(va bL(.KhkQ$|p¾־cw݂vA5{:LFUF/ƹ{w\R[ULġcOzyNoj튵ʆƖX;aj\aHWw d'b`h_{ oݻ<ed̩`sZܤch5 ,t}Y97H#뎗p4 兩8zw[CFf6X;adf 1N~X9 ޽;]ɫ5䧅00ƣtɎ,? ًڍLlR^뺘D8;#tB3kW*K0@Serv ңwݗRW] u<s[V`TclfpӒ5WCPY re^7 A5^~ghb. ;Kz3p06w*9d297@ҽ9ʒ,n-)^PjˊrZ 8'(jE12fL yr;ֵn4۸ Z8ڪ" ,6$nC2kFS&j5K(vxA09nȍZ, KR_S}_jsd Ⳣ(_|S0@&S*dl]r[{a %$$$nU-e)'Q-ʊjŢV(ۯT*^AL2V2IHHH4")DQ{\aע(\Mvx/F+MĭCDw=o++!!!oݘIHHHW-FRIJHHHb$+!!!q-Fz([AE!(QN@(@(;х9%b vpQՐ"ن P!ކ@cm(Ap4E1G%0!-^؆#sXІ`Q(jApBâ(6ݐ'b\CDQ<֐Ox<11!bUq(Q`=n`EQ oc \Ln爢x*x(`7jW @ F?x&Z5oĪ! Toi+5Ҙ4yCzS9M6+)Y5ӈT5I3iM&iQ;dMҚl裪IiCcz۔|^n .clߌ1nJcf[qc7d`(O @wQϴ0Aجnú JHjEQ, Эk[ȶ%n9Z 8-bT}SAPj]Zm޳%$n 2WՄZq+QˮArWj d2Vi`xQ urBQEKݭ `'ɿj5S;zuVy+=}upmk$V|(m\ Z]_Qj܅ZA!˿70u'~+WhהÙݵ\K<(bnkە!@.W621x)!Ѧӊ'AHվ|5̳8nG_%gVb#nʊHZ[ŦV ]dl*BPrq¢fҲDeU]!Qw] r"Kpo|%Z|w^Wj^Eæy lk"ycIJ{FMEp!ZB W(O#)^y< vq#`(?!wHH\G&+큹+P*G4튁12 i͙|X:QS]8y0NcjwrcKTo]Tݾڷ2S[s؝u-t'?;,*udIzھYd˺:_0Μ8FM>8n-lcd_p׌' g݅;d|;ǩ#ST_Wa/EU*NI\IҒbptS0މ]qc)Α}F2lܽd:'Te%lY( ̀appv)coKxsFú> HxEׯSm͐r٩"'3Yy9?c&=so}ˀaeُ8qo&|/~=|)jk`5 cKˤ麍SYQʮ-??WlcGkݙX6ZvGILQQUG+-.`ⴹԱݺ"MysoVzEey ?~5XUQNPADzu5yc7[hcԤysp3E(s}O{X@LQs)8o3y OS^ => ^lup cfnE;vؔJ#W_~1qڥMUer9,^6Vٓ:\__KmMI#B4{҆;&? VXڱŃXG܀oזodspч{ grܬcNrRplXJIF { CT!oo"P F{DEѨ1^E.W`FPԪWw ,S8puG_8gj8~h{*^3s+eJ(.t+" +Y_ rٱΟE98:caiI(sNN٢(jdsvs׾( t Lͭ b+[xvmr#%EyEP7JIجV!+#d45_7^k=,F toG"k[G=I&n8s|7 d̚&V6X80b}Tui)qu(By&ڞ|E[ςpy߾Oiq>&>wQ\/(U33]Ņb`2}ZO@LL)*ӿvEGr<@v-f 2)+E1151u]})+)l~+16սgTueH"aL[Kўw쩃D+lbn]m5a{Z_VrUF$ɵ Ҁ=ѫ3lО?WS#},<:}Y׎~@Mu%ua{d|)jk3%EkeqhFcO_ qcHI"1 AѠ40+W7 spDמڳwb`hto>ήyiݿQԲs󏔗d:DQ|Vnka+^ >#{mޅ‚l 0YvVz"_|L'_}GS;u:?cgo$w99egxw / L,,Bi`Hnօ B|k'ٷY_W92r>==:p>$rqw?rCZ-{qlN}ŃAwy)xwJ¹p*˙5-L[gxmTV.kWP Ȯv|/ɝP\K~nF1bE;hsjgcxuKjm 4==fdl_WDQ3O1g%t(.nތ0t&CrO Ahfec_Wl]061gʬgٷ} 8wb Kٻm j'p'es~Ғb142a{ޝ1rrR)-)K6OW161׏Օf}i;`]sC#cz05`+n$'D}^~]2c5A._/{½klb֬ ѻ3(blg_W,,/D35˯mBɼ׋HN# 7S% ?QX};_8";x7.n3wZ(?G7+vhd'y1,*BTa3Z tμ_8w] 0qQ'{L{ 05ļhfdyid' 2<021C4))g9t1_/}SGwhԣ]ғ: IDATh\i͸]P0 \ 3\e4Φ%+jjMӞ_7Saai.(ApE1E%$$$?L}y̑}0UE5 cڃ/P]]14r2TWbimn(v*!!qkwy8uuAʀ^%$$$$n/(DQR넋HHw s\A95%q it){1]\[!2|Vra e@vL&߫Ѩ'AWQoK\;jf}S~퇤gYÇW,7:H&r56͎ˉxF u#cѻS JH#*?@!qiY+p֋#qV]@SZUϖu_DQ++!$EqI[K!>im1]:_\U3G,x+4k d+~GY-0_lly`'?Bi`DȀ1D%?'FqR065SAxq;6Dz CIa9ٷ cOS[SŰ?N~ r1fּ(o1es-lO 2drb3'T2aAJb4gQj%$Y'նFh8s}6j/_YQCq?mE@׾8;uF=3 'o_1a\~ *ʊ ?#+-YIaݷNO-:y.L2V67o1O>̉}$zc_3h>ҕhDQ\' 7r>\|. Q]=?j/._~eU~{=uvg8)+)#Ue{c``DuScw9qq"=<v.:.8m&f=/8K"B r3ѨTWt1;W*K05$/;ҫC߰z",t[Dאh dEkM,ly?yżl#FFlZ󹾌V!5)Y,jkJO 5)QE-)QTUÈh5R9EMu%.>F\y϶_j-j511z/_K]m5UTW؛{jFM=Ba ^X=UepKRZOeE)uyԫS]UZç3yU*M?16ZIy<ʦ5_j7eFrAS0y#ԛ}F%aۈ=5qg().yosVl3!띧>A#&C艳8z罅#BQŨ 3FPb=, ,tLįK/{ ֑I3AFJZ'zAqAʈӡY‘}Q* 4 L-LJB4 )شښj,lj5d`ʂ7$>9vÏNؾq%? 9yd'A=v.棅3c+veۆotZZR *U= F#礳a'>ۏKhXl P((k~CMu%+FfZyZSXֶ[R]UAzJY|PQRKFj.nX8 "wx~|!B܏amP]012#c3HVZ".Xo>3Ʀde$rߣ2` lZ95TW0p](W6EQ^Z1r#cSسGdrl흙9v`˺/ٿsyc,lX `cD~NsnSNځuSugԜ\};݅w^O ?&) eE(J Lx,>T)X?YP{Eox%)1~*Qס40^c]"u+8ƈ3'i[@Yh:(J|1|.$vYi!TW6 E6p.w'띷$eE3sKj}hQQM}} Iqg15$27+׽0&LCX6!bOKҭ?ͥ0?wFn/WIQ>KY>gèf-oQfcJw\=[?޻b#ׯ,t#NnlZ9~7o.Ù0qG^n{+BVʼqE /;]F;/LnYO{?cu$G{/ܵ;&ƻS0FƦl;رq%.;442*ʊqrWѤ'%1U}Uе/1Ș >!'3E՟ߍj13ӻ8*JY#o<׎VEGi`DxZ}hw9)JғHO#>|!V~:%#%}u APP(u8Tz3>Lr|$Yi$Fs/AFnZmsy{)?7Yixw OB!3-z&wgdre''{!QbecO]m5YAPb`h൯_ <ߒnӡ۾@Hԫsh|3y3.Tz {407;V6lu9-VދqqfȘib`hgfc焉^Ww_ 6^Lص+7d"GMb\N_G15YHî{lBM~nB2x|Zj pv:zwai=y(*C^vG(,&*ɍ ,ci-BTaէS_WG^byE{wxwp.{3xBwm߀GL>,XQg 礓DN {Xpx0٬n1jښ*<Zy2D{9*()CVaecBϠ; @~n:>ݛY4 ήn ^P_WKey)EdvEQ$`phFrR L_(s k}(yUm)[]JOҧ\Upſ1w3pݭyCU7偹oAk_믟xiY>ַL{f/,^ؤM}k_?9vkśCCa^&y<0 V~I8Π ڗC{7R]UV߱w=mk ˯+L$-9w0tTbÙk|>$6 kkHM%7;؂%lg%;3IёZU?/ORS]|ʜ?n_nV {X/Lg_q3# ]d{ c̤spe8mo߱guu=q.2HbOKy.ٿ7 3 bq `Ԅh޺Z`̢Y]QݲW7NHfZ"%E_>܋oC#cS|e{=_9Tze=:t7蚾URûK:d}ç .7'=7\.|e-Y34%'3w?.n>}0 |FMrD]g.ظK>pud%SVRPovnC۩C# L&gE񖬩h01h5 +{gAgp褷A8w+5?N.[g:"+0if`sasW؛Sb`hĜ?߿%t(KK۱ݿܑ鏼;O#6AL%@'bhxaO;ٻ}-N^ytB&aaiӰd cs\}:9Bѡ/]bf{[=s|5U7E8M|?CzyDQK8@_WFMJbV]%2DQ3 kǿ ᘙ[Q{ $(_w:2*)* {<0Mv'kaB(5\n߸7FM}]-IϢ40T.A#iyݏ3s =qwn>YW`.g?Xݵ%N]B..6clbFY[0y3:eM}z>3XWh5{y~s ޗ㕸2,}Q{cNڻ`JȀ|i %33'gRV6ЩK[M@PzAڷ{ظ{ٺNىft)|swO@|;%OabjG^Փ?h"W(4}>ZZ]1jXu}z0Foj@/ٽM NmM ;7_΅9o`2 @7s+#7k=fApo0e)78v^ 04;|?/,͎G{n协QYBKr/pZo)fE[+][O@ok8.  @|iM^Z->zVOD]/ GJ;o4^j+K!u󣃻6гH̭&QJrq_BVMMAU_o@S^~}zhmJ'ծVszDK sXuz9u5޺!Ï/]rhFdr9 ~?F(ޗd lnk)n',->4nH'MyY1p_oQAM? !є2RZey޳xdPR>(ߝ 'ag W;xt}}j ֭(/&.D3eK:~VzqQ'(+)ԧeg$hH:ּ tL&aVzbC 2UW[Czá쌤o(+ge%XXZMc֩noZl(+fWoդ%Űc萃ĵ͆U:˓s {5/i'9ST狟F旯%;# BI̘ V|IC=MfZϽm3e\"?7ìj 3Ǟ櫏ѕR&͘ObgcbjFNf ?Z]O^vw;feKػ} ̜:.|gWZܬz!y +/3sKǜvcjf\7 ʀ}7vZ&t%RRG]mM'(&4{ڕQYQJ*f{ Τ$DQVRtOJB45U PYۃi۔ǜBTI[Fռb풧n4a{- aGkYZ|{ϝ:Rcxy hv g>%_ncߎuͼTV}WU}śV6;8Vu:}xoxG׭1w~eƣy*XMY^]}Fp-]k|=3s+l,CZvTu;?rV ?~]%&B!z[q.;GWb?&,tΘYQy᝕??xk #QSذjٙI2d4NI(+-߿G(/+(g'7>xm{%E|M/{%Ųow7v\d]3dTvl\j>IMu%_Y;1G>s{ud%wxΚR׵(j 1G2&϶ QSSEH ~1G9zmkƓwGdȘi: FFy3od%p}ObnaÁדt>~C&ҭf)l8 > DT!z b={wX3tvl^ZLK ? 86'dgؔYk%YDīM۰y"Nzl⣈\&LKdX ObtC IK}>F!?/ +k[\#l߶cOBO$)Ã>6~؃FMQ% L KkM~%_aEǜ#6V1=jʟ?˧( tkHOĶ ?z‚\] 3РC_J%c%ҧ 7mG#k{TVt|7UbCS< ސj[PYQFaA.fzE%Fğ*U5eImW!Jo)t1w=8w3 ^UplGXan*wW7:tqR35v*ήMhն3Q(xoqAd'|;TVVOvmYB8<魯\pxF%~돳k\<3q).8r2SX %qѡN"b$M[ٻJޥ 1WMs .FəS9sJIV<ۿ4:"-9^6SSvl\^-Zwٙzw=R"A؃{~:P#LaE|[anaϽ=cėsp&)>o?+<@JjVV[Xg ^і4j-8N|ͫutڏsnZ p;TKHKqA'vcnaŘ/ꃷ ==uP߮mmz4'6lCSo_vn^ư&qd&miѺw֟djfAii11R+7;d K1]hٺߎƈbY(J~ Lxk, Ḹ5!/'CT*h4RXgVoFۗ(:{gBII!޿VތoZ-Ϛ| ]O0 įO~ /Zý7>4-էT&_? /vd spZ\O&=%RUVW7ФtENoF5ݽạiKh!}5H<}s1}ϿWg{V@jƇnU4ِ`Xuok(^>9yd;qzua~FB )!(?7Ӵ uA!c 2fm7.k[{ %^Y?s]cec }3-ӗI|f}S%슍_&-03yjۙ> v(Jh';`mkTM[P*ytD3de$3v.Xc(/+f :v釣;_?Rx{'7}V[ێ=غf1qcfA2ҒiA'~\5G盏_ %)zX~C6)*c囜9uރFEv,f.Z͕Hk[{^;'z Eqa>|ju%ͼ)Ly`Ggcfn8:Gsb5űc%РR*t1ԋ_WƲuw7._B\ׇȘ>{kVe6^YBdٷ`mcOz}'q).3םٕg \ Cc&L(/`qգ׵RӆWdg~#|v*=yͯL3#Df=7`Pr!lLRvˬB29o4BQz|"B#ϼQ]?AmuGӖȢ~3qtvgGKr+XSYbg}NEd#^Ym N[\WP*#;ѧ쳢eIZr<U+K):BRѥ_oVYX\voo@1XoؔYfQ4brr˿}G]ZZQ;I))hP*;[N}efTٷ}BZm] *Jb;'{jڟ^o#Kvf*9utoF657/-ШBB*!ėRWnqUX!| 07=uu6(w̘Q(dg-%Ew~d kFBaTJR#q}U⼜L2NE>3hޢ-S_YJerMU&&4oюب3fKoڼA;ue== )%Kh^a~n~G?<=@D c ?` =[aj3Rj* rTxEE\|It @NV{y+aya3oS '^te.EGYi1gN`i 6ꛒ/ƗY!T*yoѺGn$#-Ȱz^Ӫ?:JeU+JLj)˯׼e;ԕ$űeշ<;F_={ $%)21-W{S͢S@BA^6V~Ө}dOsv4o؉3iϢOSQa+kw6Nu5keK tOfkFn)3?DeE9ppZ2ӓs},). Ykvf qBph76bLSkc=s}>؋3vVT:ueEU!Aƞs1`C^c[eŜ 9OѨ ]-Q(uj}z413ft: ;{:fci3sD_o7O/,,qt6)TRƴB mm2r ; {Z#7}׻̀aq`Z ry0TVFcthc_پi)iIs).s +jЧ)}Deb:t f>$%\eнd%h9{Zh 믆vNs/D?IH>zZ;]z &^^LB\#H68}l'ofm8wٙ)z̜Gqx/~B)). ;2{՟ E=}Ggw|mFJBѯ捲?ڏ'RXx/3ՃON.fsp: spo҂g{~nBp‚cmshR!3!H g_3j{~7o!+:qR+iݮ+z߅B$_ҧwZvG%B(Zonx4 IVCH^JK 0РN(U*Oao)+-f=1dcUk l0Wj(jk3E:vGQA.7-uyz1ٸV=H4؇a?W'N2s- )7[Jxhݾٟf9JJee++Q*UX c#ϐ'uՇ$& )Iq[X۾Nnn~gna{"%uWMiIRJLLL115ӹJ*+B7CRKilfnKBy|vӛB@VTm,,/ Jh4}.쩃8yƯX*JL,PWVP^^JLDEdkϡ8o9r< q籰C!|}LL05Eej155o/ d%ҬE[jgVCS3s}IqyH):Crb,>m:̻Ma᳙߽GQ<?ֵPyp-mXLcZ !ޅ )Qȿu\?MQA.V7iiL5rUTB{)e] ~B|(\rB6h ӈGgwzVaI( 6G7ޔRRa"OmXʈ#F42' 4qyrf:=@!W! 5IQ(Lj#NNrbA!D}| \fm{]`,0 ~MZI)k䪽g7K-͈#F$GxwRF Rr x̪U].򡏔rZc]#F/q3L)e) ՑRʐj#FKL!vBw@ ª=BUBcA#FpmLc!h xpZ| X he=B|-v'(/+5а /[_&%Aѐ~j$**ͺs3dEnv^Ea{{5+)/RD)xtVK4^A]YO_AyYMljlQ]>#YٲO|9>5/̭|2kuO^$J̙Y4oumsvxm﮽uɬǞkTۨsc7܆Rե K)Rܾn1E:D ^Wnԝ Q| h@Y\oAט5~#B(#|oz $'(O8t_H)|&R3eR˼90Sܱy)XZےKH*Gstf n9bǦܠ@M#9o%Ezh*2Xz;גKǮ LOkXZpyz3陷prmš_pJ%2ng\V/>%40{T~F<$g/0?%'9)~CZ围jۅY_Vt~+bsQNw3~U]K#c/=Qgط}kLAY]:?bk*ee,^07.\;xkLOவxk1=͡uwpOEIq!Ayww8'1!MӼ2^lNAZJ+{Ɣ>!. Uf0gJ4/^|.0奏sH.91/?f~dڸFKfzR=+(fOХ`  /ᣟ`,KK3wZ3)).p1}h4_I3LJش*+˙37Z'?7'V'grZJ)`c'LIQ!<#EoVW0gx[aecLJleګrp:㣨(/\ȾbaiMF]p "IN5z;#\J y[vzB j{'!'u4jn:Av{ۗfmhӡ;Dٳ S33#: =߃Gt9}v;wOo ;{'ï9GOΑ?IBl8Da:2쾉vTw _[uF.ܛCF,Dw88ѭ0ZuQgص?-}qEмUߒɸoԻOʄbkDS/_: œ&^d^wīe;vls')).Ǐ^85 /|6.b#MphN:)լ\C]YK(,#/'Xk.}i۱^><`pvmB.?VaƥdQZRD|GۮcOv쁙gШl߸, r ':<}G`cWyv]3j۱{baiCtDHEqQ>1q[ vM(* u1MZӺ]W|tѕGbemGӖ^)ΟCۘ0݋ƠW)ՋY //[=u{_fe}%C2ARQ^%8:m KEy&Wkn[LL VVV`fnTRR^VE6 #- )u FycZyCX*ٶ2hT*)-)2И-c0flX% 3szBwM?VWƯ;RJ$Y]UU]Rrr q4i&-RbfnFj;C^Ջ[ԣ[+k+ muu)U%*+˯Gގ1_jW{G}_ɍrLLvԧOο'o| o?o7QWI¢zUr|0Ggw.߿G^N~tfWI>v̝;M|9}u$_*\v]mBn5WT@L߀9B}i^Fg=Է{S^qTI gߡ[d'Ŀ[2Ғ:lФ.*O9~pkҒ"b"W[MN#& s!Gn+k[$GzG`ԋc6woⅫG3 %CGׯl܂-|)%Rg?;,uȳ`)e%d_F2v ή68 fDrاyWwp !a' ^X]IȐ:7;rm:q. 0&8N 틁%@Қ-ѼZiۑҒbG )%RJ 'pZ ,|g JsKkv.<8q_}}V2 ճ-AK_}h*S W>Nh5WjkiAf3ocR}A  {'OZBga_8utju%Gq`'ә}7ٽεgh͛λ/Nןlv+BmB0陷ٹ**|88oc"[Rib0p|z>{rdFޚ>SS3-o$I 7{_z[;: `rWcZ !f3IDVST?/Ǎ@kI%'+ GgwPx :tŠQcF(d5ܬ:|yY XXZS3󱲲We֜%]'T(;3nZJKa**ʪZ~M^`[F);G~@ʶg(.*@zbYi1(JZMU?WjI))+-ҷ(/CTVo4TKeѨqpr>1ܟX Բuw2~ꕒٙ)sI@ebZ]ɷ^ c]5f VVVvTV\Re(R*Q}.\5**:j.wr񤬴3sz}9Yi(J{K jԘ[4ze%fޤNRipans++Jl=G/0u>j=4j୊hX$ ]ԪU߶)c \W\te/Nw lT)3bĈCB&n&ozK)?RVT2UFHK<ٿHUc7YSHIc߹~uBr {MR\5MqQ>GneshzNqC(/-u'GuTy9Sgyc8}lgr΅\ysj^V 1x))+T|N(Z&H#ٱi /ԍzHIcW,Z _~ ƒ(+-iorr_/]dۆFKC7pt_j];RXòoġm,EaA̫IQS\Th󚟛IaA1獳c@O(eclBK);4f*H#J2R8aN|`_~ 9P(tҗ ᳙5 1ccw%j9}l/5۾TPpho|IXaX=%Ņ8:Y|!YɔҶc&Lˎj5l+ԙPLuѧ )2 < /v빸7 WnVW=OA^x;}8{=wC2Exiߩ7?~:InV̪VMH>}IJwreE\%y|ܲ k{R.q'/'c7cc@iqԧ~9 oR^^JnVc&@ر R_>fsqqozU-(}B\xq7#Y3Jet>4|E sQ*MiWT_c"CY&WW/OǮv$\aA仿Jc'xq|XXZSYQ'z}&91,ZΑ-Ғ"MK!;3>ÙW Q 8W3ppreU| XARNB\8>]M^wXtw?09W2n_I9޾q !x덯,+-/6ޗJO .8ߙ R ֧!6|=LLLyHK/:<21<Ϊ%xpK̞cƿHh!@tB ?` QOʟ1 &4]ަCwci[@+e'#iRB4:^  ^tHGdGӽt{7gOgyxQXӮjFSIm:t׋Ӵn׍8<\u$^D]YɖUW"Z}#/?\NFհaŗUԤ$őCz%: Kϡ }`mc_w7ch޲-I$1ŅM'/F_(J,,m}3m:?nٻm%闩/.B{ހ.Azz@w/_Fy\SǨҼe;PT=醙+fNVPTgQdjfNqa>RJdajfx٭)%<WO/,my,^ ]z:R /[/k2RЪm|NV*S\ǯd_uB\Q]:cI9Ǒ#)NNDc88BDX Qg  l>m%40vΜ=u;סT[낉aAwt!8pGmƞ6~ڽ*G ȰDұ[ĎC믁L||iۡGUY‚aXT::3nۿzs_jۉ{tWuRkcffAVF2%ŅؓXXY_^i 3tҏ }IFZ/+k;l휰sɍs/P(2C}pvkw _8'x f>[ץټͫ1ft|1) W.bÊ/dThx=3N8ѹpQ~yֶ,?F 7/읰w֑o}GiI_},%L:!n^'Y8g8c_0u̻ CGM`ϟy7tu^ŭ^I ,aEU,ϑΤgFPK+۪3}ηՇRTio!`􏩬(/ޠE4+mmkO@\86ģONמCuSw|x=ys.ϽnM:j!#7ͫQ\gEHvOVbs=XwuyYU !k)RJk7."1>஍\ բwÆ%o̍F$P^Vj֨uShH)/T& ƁxM!T?1r" RQK8g̖' R/nĈV*U)ea t%zCi49F1r߈<ШO^'Iq1SVÿVyu߉:P7bȿv0f/ IDATX֯BSx&jFa),3:ly/)zZBTT^mF1r+/ި,ˎh]uT k5!Z}2)ef6KR^AP,j4Z:G\#FYGWue w{qw"HpiZgP|u ZJH[Jq q!.OK 0skV8v=}geF^~MvlZBܢjoBԜlB\z>@R"d o2~Cxވ$I˔J'fVQS_ Ȝ 4~* (+ʡ(C{mM:Bէ:w04}AP#<%5RftHNk&IP(nIsV'  EBhׅLJ9I!B}A != B$f Jqkˢ@Ȍ&jkYB3:B)"Bt TxФ \{@!7B?s~$I'C7݃Jw!^z722222!R1܆;1y/86Б'p&$I@ lj}M @gvɩk9B)Cn8$iRzUTZ IgiNFFFOrcN')^QVyRTu%IZ>^FFfQQYOYQir]B.B<~&c;$Iz VaП:#`tWQ?PX Q#GfRZ W,SԒmno>yYi*B#$i'؟z_| !>%I2VTiNΞ{mwT4U#Z&D~lINg`䉑 !6  iz#IsJѓϽ^:U,gaL8V,3s+ƅF1U%VT9}XFݏR6 kn(֖z= dc};9y3gܰ '(&l 9ePCUy;z;qviki.ti)#P!%IR0tUxiP@!p(I$=qJ`ϖX;sD'l^ Aay5-Ψg6 ;G\}t{{[3s!9~!tn[:PҚe^sk47gnaWuR9n>w)?cd˗=;+?#wBP~9_(/%WͲkߎ7Õ+n$!Ķ$y]jHR/ѻs@"MR*]rVӤ'PW]&GI8<'7W''=7O?ܩ*/^ˮ)uvڪR:{0)ֳu/k[?t_ffxB5\|ŝk膺 K?t̸CjSv};|_%xtB'l9S!%IR(ʩοL߰VZMq~&$anaMWg۸g}dޏJejK./`Y KWCf~}xP(Mэ SVKStvpv}=f&Ey=x.%qAHDVf?j*MccSBjon0 $JɳGB[^rc/U&o$I1̥+鴦gcD}$=y0ūigHIIWgvOMF?orGNgǕs",B犯?@a`GL1擗)KoD.Y~/.n>eٻBR[]ʺ/ߤ/aUwInF߭^y&]7氱sN^BWFGaDyhT*#䏒@Uy!$sށ9TGrv<XFxR^~:)|*JK+[&O[0Sg^]+/{OJRYFvnwyGJN.^l=򲒇cjf~m7Mݧ\\Cz,aX{~S(LfJo]t74׾ͦWz.~ uSLL9W߃']Fӧ"7#-)-ʦGlms>1;ڪR(*κpX9K+Psb#3e?0{DO_BrFgnt 7O0 E[.9l֎oaFͱޓ-"tZ- b\C؁WQ-, 8wÇZkC]G1O f}\όy{e' {hgGM>6ۮ#T ڎ|a&NuZnc.nޥg&fk@رSf,҆:r Љ19F*##|,/#IVP[UBML4mtwuPΥ 8]<* 7y,V^PVש]#/B>>C9oQF߱x*̭5Hr9+aޠF2Ĕ'^]!.j*KN';-YcQX!%qM 0Kf '$RȒ+b;ѷqCmg`2lTy:8G i3wk?m?@8Cz~ތaioP9Gw\f I <}ơTSR_7'5rtXGJNT*#xV~x3s+zIx22SckD@p!mRsFڡ=GTP(|wA] %,<Xe]N(/Ss&O8gD ♏Y\~,&Ş7:'&K'R_S> w$iі俁ԃzSO@OðUo>JM&`oIME@p.GgOj*KXަ0/ NsOɳ۷TWG5-VSYO윋]ANf7Fscq;fSЇ"I bs|$I׵2 ;',ukfbL6VT]m- ξaim=1N&h|%WUDɍҢYOl,3ZV_[A}Mz,L90; 'u̻jJ 2{9+kH/ʖ+oZZ&fg0?wBtw퍏v\$DuE-S!IW0JUC^Xx,K[vߩ,˧0;zxo0W0QFLHKF^\=sm`ԫP(Y֭}}WC[n̻എ 0 115Gb͇RFcKX~#gtcS8yqɃO}4b91s Cgcf\~9Rw|UF\}8:{0}%3U~ uJ\ziENyVYB>6_ܙcC[K#G6(܆v~!yA^!J &x|4aӎ[8|5\}xM HIډPϣ~ K&D0=#itvW`ai}:͍zZ`ƅN2aB Tblb_(3ϻ oc}EyH4EЁtZ S}QU^N;Y_nX {]VցRQG/~EƦjsSR!4~ ]b삟.cF`oTW܀7Ni;%~!oD]NX6>z;q e~aZwtc\hETabjnP[]a}lRʊrPǰeddd(Ј銁P22222g,&#### ɑ9H~mAddddxM!t_B65Ȝ]>THhKq6lemWs/73,^z :5z;BׯyxEc=?p|3?6|8ONyɑ?|EzaߏDהiyvŕâP^^yFj*Kp;wegv 'u.!تɿ*yϙ:Bc}4X z*+0)/9fVmv)s=u_m?i+ t .6gq?|E*Ow|2]mHs`{Iq-()pAdGrV|C>w vYL~DLK@pM 5ص:]BPdBJNVc}hsdܥPRInF>\q.>\x#*(b϶@.v=dT`lbʌ2>r:l"Z59 _s2I3*1=]88ܧ7bnaMAn y4WcimEWujkpqoB !u`m߸ 99e.5U%d+vp7x^Xس(-o>N{21m Jw!(<2ڪ~ܰw?5&,b]utwup8a;~'Ϣ| Zm0܌D"%io|XwtcK9~M)TFP[wW3BBc⃧:Oy7O?ݼ(;~M:Z*Z2:%ξ?yqGʖo>},@>}Zr!y|%}I-݂)N|XX>yl}~c"blWPM]u~{G<;Os=CcLbK:_1캥ټXȇ OȄS0"9~+}-|2~&Tx(-̦߾O[K#Sg^]ٿck#chmկժ*/dւ˱sCR]Q-5 IDAT f(KyO \/\B9rc륡Hm_qeJ66ʲkb"`ddL@p8I;IOCvZS1}R:2I z Rń22,W_{:P*Q(GP(Ш(.$|,^|WO+^ݼY6ow422.a6~}<ҚeŢKnH֡޷*T*#cIIINF $݄> Ё\v}(uEO}~I,\03"V.Xv .N؁B7 KnDղej. RZMtZ-K qA֮zkop݄='h1 (qq烯T*8,Gr6ϻ0,+!ifC"13䪛Ĕ܌DCc | yޅJlhk 0.su5e67Kn  ʱf\$-0œ[qpvх> @an*ե4ճǰw>s: RItRvΎV}$'[ccH̬ i[)A['OOx$I' 50261iom1w5S]QD[~AwLLhk_E$\} u:C;JxCޤho_eouwat[hk P {b4(OOwglb ?B7opoddV /+[/ $I2<W}fdlNGgCWG{ C~>Xw_c[Yr'샿!; `ɨ\}≽w>*w>*^9WzǓQQrj3?' S;x2 cڷ:XmW\= __ ;\})ItZʊs}`vt?Z}lg7o},\z#w>*K S-ټ.N^xgfIA"%IBgYWYLLLwq^ry`O |ŭ6/KnO^Pm{SfPeIRRX @كi|߳b芑nu]JoOaĞﰏ'fB'fBaA\= m+`@S3":6|-{tZzOXw{37_ý9x-u>y6zqȟX1544Ս%/}_ KsSxtu(/ɥ+ٿcq;7_.O%I➇͛cw_HXD,H);Y;VތFݏox-67QEĂ%7[#fdŘ[X IVj .{G~XoaRwPW5 L(/^'/˰KI +SsZ v_N~My'e}+n<w.fE<+{J 29 SjՋxRZenʻټcʊs0G76/'3e?/?~^'G7?ECmִ4\F3bP* de'Idf̻}ӷ|wu[t|ѳ(**Ytͤ'VڎO~ Q3(.$"zラ3ViI !gE I2ֿu_ι2GNvƅF3QSQ9 tw2q,CZ{kaj>1j&vU/ϧW NOw3ym^3,_Aq~:e{1,z Et4>ڐѨIMڅazBRwbjfΖ9 s͛GF[K#Y w q4LkK)Kg| L,N;@Wg;Eg{ r??q+ݽ=]dJeF7`<~erPU^H4m9I8SrfV5Sx$I1Qޞ.&NEyq.N.cx'qvœNRpbGRfbg_$)BGfJ: Q3PX_EmU(%G()D=ˣ5} !L$it4c4$ (ՄL:{ikm ]Q22n.-̲?oY)QSFg 'Q?A߀ hqV._Wl$I !!BQvTZY]̭F[ߍVWk*4q1sHNggGkW<?}HuyNvl$I q!ZFڡ"###s.PRɦV Np"PJzkn{L9gᕣ-isYM_owV!'HQl%$I2G^AEL<2222c|.9~BR( Bؔ$v,$Is*5J=x?h7p~!x222è(ͣ0,]nfNתjnB2ژU$YwJbRQxYF2鴉:. DܡH%˅"q$IіEFF5%85cf皌 ║9H4`!{a mՐH6s bHmC9搴5H9$-j vH!W 0$iI[4~@ǐ%C~5ҾvِiAC );}|H/?>6q/9>~տYfl_AV2222gYȜed+###sYf<#$ICTeedddB@L*W$SN+ih$###3RiT/.Q]!Dʏy?^Ib Hl68`dbqdddd">Jhk(PXjڅN{W$c$Q{Ah%###sBԽdPW]$ŗB1ycV*/$Iq}茛~K$9̹AuA>hԽ)B&D1&$IHݍ WG-iio(AmQtZ5퍥t4(2f{*n cn+IPMqrcpRs#_P ;\[8BF&lf4^݋G\ 4I0t?k rY5#tZ,l02sۖ9IXKa~!tcNIRedj>1'۹Len6$ِQ9+WurƣըuGedFOG%H BS%veF˱P(O=w2I?rf%5h5}83~m{\-N('}'ciB (P(U:bf8bB+{t~J#@ [:-=uXغֽ^BL- Z$IPOvP(16>ZWBחT$)I\|Pxx~d\|Kϣ2t4`nsfA\5=aqL=!tp}u_ގav542XWx6Q(UO]:e I,]0$In˸忊┍ʘI<V>L^{j g{yIP[@l)فЪu &|Q}uganEPZÞ9wRB<4Ue݊;vn!θ BIFGVKPr~xM7ߏGlo~D0Jξ^cP=mxT$IGZhH#hՌrq@edoc3^ !tL)BNgH s{skgRD\cZjPtZvs"/C4fw /kj z N?AX}`jak42cL[Oƪ,Tf0q(Uū&3.o35L *'X$D4} R%tZ ŔoT?:lof]EYP(p򎢧M_3PBji5^O{c }ݭn{8*cn$LmBRsuOTN*rwR[poLsܮ_63tp"?hs+ޮARu~Mn^Ť V IMXJU^/|K!'(N#îadbɤ Vcdj?3^_}`91< hlj?伛wԖ24&̹niף=W3alfMWk ipxJvyI?=G@&f68L_"p;VLmq 6qW{3D.; {Q)T]>q1GV_%yWLp!\2ɋ漛Wz>A]"ݼ 'H2g[@ )SNVuB*ClJ1>A)L֏Z+30Gՠ268$}#S^:Z*q0 3=a!AzjTZj(Mb+3)Ao~f[} 017B$IA(ID_qK<\j0e|p0 >7kG_ͬi'};exfނ{ T 5I?`iPi?^ػ>ZMi̟RP8)j 'ɜ9t4X:b~gsP&3+g>,=ho,`Ъ(a(#I*cP8tZ H>X;Rqձ e2 %VާTF&E\_ŀ<Dmq^kcEaQ 8g+3i9Bs{"3hσ#c`fhȌjNkp'kO%EUu[cػR[Hsu.5E L3uPG_=tXjZmuZ:`6U`baǂ[?]#ח&S[1KkG?~0)nNZ/kT܎W>0sp=t TFN"w'hk(?YO8zN+R2ʳuɈ~v`Qβ-kdBL "ǚ7 -~Kqi!/kj(NčŎcVq$a-%}aP2uȔ& סjh(Ocwkݜv4PP[XA}iq夁۹.rFk}!Y{W:i={P{io*#c%ROI&P*E a]3}t %N^°pp:xσ>-uT!8v+q?|{}:4 (15Bt(FM~AF[ %%uۛt6Wa&vL{7vc3j.8`Hs~;q1E)ȍ_CQOڐicxwGkFL=02ɟtr|Aogw𜀫Tj(JYV@uo ͠(8*swS{X/3*tL]b y1DOG{# 똳$lm:Pʑkl&dugGPVbb6 %'wX$) )yQxyixdXE 13x.B $ G_\q߰w;jfh̤:k'?c Lw ;cS}k@ .7@!iػ^K(U&x'tM(FX;`j利=&hiع`B_wvA8xLuoعaVӏ}p pmSc>ୠӪj;$cnNA4 [qxOXy`<&.I "uX{2~ aMp#st: .Zʸ)W@M-Ш{ f[tgH(Ux%8ZVӫP97[`x@ [ d_CoW3ɛ_tBY I<`n=wTCwɜ$|Es a敯8" I`bfC_O܋2O yk3nʕLOhS\&gu:&D1>L B$I7tf}0IދDM٨:r7ԍ2̬O\\4c3e) ơJƠBJ@I:+t Wf$IYTwl+o^AQ:ih&-3@Zu/}ݭعS,󿇦}v[f̙"I\BV4r8.{l}QFFFf,!"hzںN{ʎi I%oCR(uV^[ c[T򊮌(2s._Pi2 =IDATB@̵wIX ZPM, ȜHZRjC!!Dʩj?ظ*T IENDB`stxxl-1.3.1/images/layer_diagram.svg0000644000175000017500000004427511437173641017323 0ustar andreasandreas image/svg+xml TXXL S files, I/O requests, disk queues, completion handlers block prefetcher, buffered block writer Asynchronous I/O Primitives Block Management typed block, block manager, buffered streams, Containers: STL Interface vector, stack, set priority_queue, map sort, for_each, merge Pipelined sorting, zero-I/O scanning Pipelining Algorithms: Operating System Applications stxxl-1.3.1/lib/0000755000175000017500000000000011536252420013260 5ustar andreasandreasstxxl-1.3.1/lib/libstxxl.symbols0000644000175000017500000003003311341242304016534 0ustar andreasandreaslibstxxl.so.0 libstxxl #MINVER# _Z20gprof_pthread_createPmP14pthread_attr_tPFPvS2_ES2_@Base 0.9 _ZN5stxxl10disk_queue11add_readreqERNS_11request_ptrE@Base 0.9 _ZN5stxxl10disk_queue12add_writereqERNS_11request_ptrE@Base 0.9 _ZN5stxxl10disk_queue6workerEPv@Base 0.9 _ZN5stxxl10disk_queueC1Ei@Base 0.9 _ZN5stxxl10disk_queueC2Ei@Base 0.9 _ZN5stxxl10disk_queueD1Ev@Base 0.9 _ZN5stxxl10disk_queueD2Ev@Base 0.9 _ZN5stxxl10ran32StateE@Base 0.9 _ZN5stxxl11FileCreator6createERKSsS2_ii@Base 0.9 _ZN5stxxl11FileCreatorD0Ev@Base 1.0 _ZN5stxxl11FileCreatorD1Ev@Base 1.0 _ZN5stxxl11disk_queues8instanceE@Base 0.9 #MISSING: 1.0# _ZN5stxxl11request_ptr7sub_refEv@Base 0.9 #MISSING: 1.0# _ZN5stxxl11request_ptraSERKS0_@Base 0.9 _ZN5stxxl12DiskGeometry8add_zoneERiiiS1_@Base 0.9 _ZN5stxxl12DiskGeometry9get_delayExm@Base 0.9 _ZN5stxxl12mmap_request5serveEv@Base 0.9 _ZN5stxxl12mmap_request7io_typeEv@Base 0.9 _ZN5stxxl12mmap_requestD0Ev@Base 0.9 _ZN5stxxl12mmap_requestD1Ev@Base 0.9 _ZN5stxxl12onoff_switch2onEv@Base 0.9 _ZN5stxxl12syscall_file5areadEPvxmNS_18completion_handlerE@Base 0.9 _ZN5stxxl12syscall_file6awriteEPvxmNS_18completion_handlerE@Base 0.9 _ZN5stxxl12syscall_fileC1ERKSsii@Base 0.9 _ZN5stxxl12syscall_fileC2ERKSsii@Base 0.9 _ZN5stxxl12syscall_fileD0Ev@Base 0.9 _ZN5stxxl12syscall_fileD1Ev@Base 0.9 _ZN5stxxl13DiskAllocator4dumpEv@Base 0.9 _ZN5stxxl13block_manager12get_instanceEv@Base 0.9 _ZN5stxxl13block_manager8instanceE@Base 0.9 _ZN5stxxl13block_managerC1Ev@Base 0.9 _ZN5stxxl13block_managerC2Ev@Base 0.9 _ZN5stxxl13block_managerD1Ev@Base 0.9 _ZN5stxxl13block_managerD2Ev@Base 0.9 _ZN5stxxl13sim_disk_file5areadEPvxmNS_18completion_handlerE@Base 0.9 _ZN5stxxl13sim_disk_file6awriteEPvxmNS_18completion_handlerE@Base 0.9 _ZN5stxxl13sim_disk_file8set_sizeEx@Base 0.9 _ZN5stxxl13sim_disk_fileD0Ev@Base 0.9 _ZN5stxxl13sim_disk_fileD1Ev@Base 0.9 _ZN5stxxl13ufs_file_base4lockEv@Base 1.0 _ZN5stxxl13ufs_file_base4sizeEv@Base 0.9 _ZN5stxxl13ufs_file_base8set_sizeEx@Base 0.9 _ZN5stxxl13ufs_file_baseC1ERKSsii@Base 0.9 _ZN5stxxl13ufs_file_baseC2ERKSsii@Base 0.9 _ZN5stxxl13ufs_file_baseD0Ev@Base 0.9 _ZN5stxxl13ufs_file_baseD1Ev@Base 0.9 _ZN5stxxl13ufs_file_baseD2Ev@Base 0.9 _ZN5stxxl14IC35L080AVVA07C1Ev@Base 0.9 _ZN5stxxl14IC35L080AVVA07C2Ev@Base 0.9 _ZN5stxxl14resource_errorD0Ev@Base 1.0 _ZN5stxxl14resource_errorD1Ev@Base 1.0 _ZN5stxxl15syscall_request5serveEv@Base 0.9 _ZN5stxxl15syscall_request7io_typeEv@Base 0.9 _ZN5stxxl15syscall_requestC1EPNS_12syscall_fileEPvxmNS_7request12request_typeENS_18completion_handlerE@Base 0.9 _ZN5stxxl15syscall_requestC2EPNS_12syscall_fileEPvxmNS_7request12request_typeENS_18completion_handlerE@Base 0.9 _ZN5stxxl15syscall_requestD0Ev@Base 0.9 _ZN5stxxl15syscall_requestD1Ev@Base 0.9 _ZN5stxxl16sim_disk_request5serveEv@Base 0.9 _ZN5stxxl16sim_disk_request7io_typeEv@Base 0.9 _ZN5stxxl16sim_disk_requestD0Ev@Base 0.9 _ZN5stxxl16sim_disk_requestD1Ev@Base 0.9 _ZN5stxxl16ufs_request_base10add_waiterEPNS_12onoff_switchE@Base 0.9 _ZN5stxxl16ufs_request_base13delete_waiterEPNS_12onoff_switchE@Base 0.9 _ZN5stxxl16ufs_request_base14check_aligningEv@Base 0.9 _ZN5stxxl16ufs_request_base4pollEv@Base 0.9 _ZN5stxxl16ufs_request_base4waitEv@Base 0.9 _ZN5stxxl16ufs_request_base7io_typeEv@Base 0.9 _ZN5stxxl16ufs_request_base8nwaitersEv@Base 0.9 _ZN5stxxl16ufs_request_baseC1EPNS_13ufs_file_baseEPvxmNS_7request12request_typeENS_18completion_handlerE@Base 0.9 _ZN5stxxl16ufs_request_baseC2EPNS_13ufs_file_baseEPvxmNS_7request12request_typeENS_18completion_handlerE@Base 0.9 _ZN5stxxl16ufs_request_baseD0Ev@Base 0.9 _ZN5stxxl16ufs_request_baseD1Ev@Base 0.9 _ZN5stxxl16ufs_request_baseD2Ev@Base 0.9 _ZN5stxxl17wait_time_counterE@Base 0.9 _ZN5stxxl20simulate_async_writeEPiiiiPSt4pairIiiE@Base 0.9 _ZN5stxxl25compute_prefetch_scheduleEPiS0_S0_ii@Base 0.9 _ZN5stxxl4file4lockEv@Base 1.0 _ZN5stxxl4fileD0Ev@Base 0.9 _ZN5stxxl4fileD1Ev@Base 0.9 _ZN5stxxl5mutex4lockEv@Base 0.9 _ZN5stxxl5mutex6unlockEv@Base 0.9 _ZN5stxxl5mutexC1Ev@Base 1.0 _ZN5stxxl5mutexD1Ev@Base 0.9 _ZN5stxxl5splitERKSsS1_@Base 0.9 _ZN5stxxl5state6set_toEi@Base 0.9 _ZN5stxxl5state8wait_forEi@Base 0.9 _ZN5stxxl5stateC1Ei@Base 1.0 _ZN5stxxl5stateD1Ev@Base 1.0 _ZN5stxxl5stateclEv@Base 0.9 _ZN5stxxl5stats12get_instanceEv@Base 0.9 _ZN5stxxl5stats12read_startedEj@Base 0.9 _ZN5stxxl5stats13read_finishedEv@Base 0.9 _ZN5stxxl5stats13write_startedEj@Base 0.9 _ZN5stxxl5stats14write_finishedEv@Base 0.9 _ZN5stxxl5stats19_reset_io_wait_timeEv@Base 0.9 _ZN5stxxl5stats22increment_io_wait_timeEd@Base 0.9 _ZN5stxxl5stats5resetEv@Base 0.9 _ZN5stxxl5stats8instanceE@Base 0.9 _ZN5stxxl5statsC1Ev@Base 0.9 _ZN5stxxl5statsC2Ev@Base 0.9 _ZN5stxxl6config12get_instanceEv@Base 0.9 _ZN5stxxl6config8instanceE@Base 0.9 _ZN5stxxl6configC1EPKc@Base 0.9 _ZN5stxxl6configC2EPKc@Base 0.9 _ZN5stxxl6logger12get_instanceEv@Base 0.9 _ZN5stxxl6logger8instanceE@Base 0.9 _ZN5stxxl7request7io_typeEv@Base 0.9 _ZN5stxxl7request7sub_refEv@Base 0.9 _ZN5stxxl7requestD0Ev@Base 0.9 _ZN5stxxl7requestD1Ev@Base 0.9 _ZN5stxxl8debugmon10io_startedEPc@Base 0.9 _ZN5stxxl8debugmon11io_finishedEPc@Base 0.9 _ZN5stxxl8debugmon12get_instanceEv@Base 0.9 _ZN5stxxl8debugmon15block_allocatedEPcS1_m@Base 0.9 _ZN5stxxl8debugmon17block_deallocatedEPc@Base 0.9 _ZN5stxxl8debugmon8instanceE@Base 0.9 _ZN5stxxl8io_errorD0Ev@Base 1.0 _ZN5stxxl8io_errorD1Ev@Base 1.0 _ZN5stxxl9mmap_file5areadEPvxmNS_18completion_handlerE@Base 0.9 _ZN5stxxl9mmap_file6awriteEPvxmNS_18completion_handlerE@Base 0.9 _ZN5stxxl9mmap_fileD0Ev@Base 0.9 _ZN5stxxl9mmap_fileD1Ev@Base 0.9 _ZN5stxxl9semaphoreC1Ei@Base 1.0 _ZN5stxxl9semaphoreD1Ev@Base 0.9 _ZN5stxxl9semaphoremmEi@Base 0.9 _ZN5stxxl9semaphoreppEi@Base 0.9 _ZN5stxxllsERSoRKNS_5statsE@Base 0.9 _ZNK5stxxl11request_ptrptEv@Base 0.9 _ZNK5stxxl13ufs_file_base12get_file_desEv@Base 0.9 #MISSING: 1.0# _ZNK5stxxl16ufs_request_base4sizeEv@Base 0.9 _ZNK5stxxl5stats10get_writesEv@Base 0.9 _ZNK5stxxl5stats12get_pio_timeEv@Base 0.9 _ZNK5stxxl5stats13get_read_timeEv@Base 0.9 _ZNK5stxxl5stats14get_pread_timeEv@Base 0.9 _ZNK5stxxl5stats14get_write_timeEv@Base 0.9 _ZNK5stxxl5stats15get_pwrite_timeEv@Base 0.9 _ZNK5stxxl5stats15get_read_volumeEv@Base 0.9 _ZNK5stxxl5stats16get_io_wait_timeEv@Base 0.9 _ZNK5stxxl5stats18get_written_volumeEv@Base 0.9 _ZNK5stxxl5stats19get_last_reset_timeEv@Base 0.9 _ZNK5stxxl5stats9get_readsEv@Base 0.9 _ZNK5stxxl7request5printERSo@Base 0.9 _ZNSs12_S_constructIPcEES0_T_S1_RKSaIcESt20forward_iterator_tag@Base 1.0 _ZNSt11_Deque_baseIN5stxxl11request_ptrESaIS1_EE15_M_create_nodesEPPS1_S5_@Base 0.9 _ZNSt11_Deque_baseIN5stxxl11request_ptrESaIS1_EE17_M_initialize_mapEm@Base 0.9 _ZNSt11_Deque_baseIiSaIiEE15_M_create_nodesEPPiS3_@Base 0.9 _ZNSt11_Deque_baseIiSaIiEE17_M_initialize_mapEm@Base 0.9 _ZNSt17_Temporary_bufferIPSt4pairIiiES1_EC1ES2_S2_@Base 0.9 _ZNSt5dequeIN5stxxl11request_ptrESaIS1_EE16_M_push_back_auxERKS1_@Base 0.9 _ZNSt5dequeIN5stxxl11request_ptrESaIS1_EE17_M_reallocate_mapEmb@Base 0.9 _ZNSt5dequeIN5stxxl11request_ptrESaIS1_EE19_M_destroy_data_auxESt15_Deque_iteratorIS1_RS1_PS1_ES7_@Base 0.9 _ZNSt5dequeIN5stxxl11request_ptrESaIS1_EED1Ev@Base 0.9 _ZNSt5dequeIiSaIiEE16_M_push_back_auxERKi@Base 0.9 _ZNSt5dequeIiSaIiEE17_M_reallocate_mapEmb@Base 0.9 _ZNSt5dequeIiSaIiEED1Ev@Base 0.9 _ZNSt6vectorIN5stxxl6config9DiskEntryESaIS2_EE13_M_insert_auxEN9__gnu_cxx17__normal_iteratorIPS2_S4_EERKS2_@Base 0.9 _ZNSt6vectorIN5stxxl9sim_eventESaIS1_EE13_M_insert_auxEN9__gnu_cxx17__normal_iteratorIPS1_S3_EERKS1_@Base 0.9 _ZNSt6vectorIN5stxxl9sim_eventESaIS1_EED1Ev@Base 0.9 _ZNSt6vectorIPN9__gnu_cxx15_Hashtable_nodeISt4pairIKPcN5stxxl8debugmon3tagEEEESaISA_EE14_M_fill_insertENS0_17__normal_iteratorIPSA_SC_EEmRKSA_@Base 0.9 _ZNSt6vectorIPN9__gnu_cxx15_Hashtable_nodeISt4pairIKPcN5stxxl8debugmon3tagEEEESaISA_EE7reserveEm@Base 0.9 _ZNSt6vectorISsSaISsEE13_M_insert_auxEN9__gnu_cxx17__normal_iteratorIPSsS1_EERKSs@Base 0.9 _ZNSt6vectorISsSaISsEEaSERKS1_@Base 0.9 _ZNSt8_Rb_treeIN5stxxl12DiskGeometry4ZoneES2_St9_IdentityIS2_ENS1_7ZoneCmpESaIS2_EE16_M_insert_uniqueERKS2_@Base 0.9 _ZNSt8_Rb_treeIN5stxxl12DiskGeometry4ZoneES2_St9_IdentityIS2_ENS1_7ZoneCmpESaIS2_EE8_M_eraseEPSt13_Rb_tree_nodeIS2_E@Base 0.9 _ZNSt8_Rb_treeIN5stxxl12DiskGeometry4ZoneES2_St9_IdentityIS2_ENS1_7ZoneCmpESaIS2_EE9_M_insertEPSt18_Rb_tree_node_baseS9_RKS2_@Base 0.9 _ZNSt8_Rb_treeIPN5stxxl12onoff_switchES2_St9_IdentityIS2_ESt4lessIS2_ESaIS2_EE16_M_insert_uniqueERKS2_@Base 0.9 _ZNSt8_Rb_treeIPN5stxxl12onoff_switchES2_St9_IdentityIS2_ESt4lessIS2_ESaIS2_EE5eraseERKS2_@Base 0.9 _ZNSt8_Rb_treeIPN5stxxl12onoff_switchES2_St9_IdentityIS2_ESt4lessIS2_ESaIS2_EE8_M_eraseEPSt13_Rb_tree_nodeIS2_E@Base 0.9 _ZNSt8_Rb_treeIPN5stxxl12onoff_switchES2_St9_IdentityIS2_ESt4lessIS2_ESaIS2_EE9_M_insertEPSt18_Rb_tree_node_baseSA_RKS2_@Base 0.9 _ZNSt8_Rb_treeIxSt4pairIKxPN5stxxl10disk_queueEESt10_Select1stIS5_ESt4lessIxESaIS5_EE16_M_insert_uniqueERKS5_@Base 0.9 _ZNSt8_Rb_treeIxSt4pairIKxPN5stxxl10disk_queueEESt10_Select1stIS5_ESt4lessIxESaIS5_EE16_M_insert_uniqueESt17_Rb_tree_iteratorIS5_ERKS5_@Base 0.9 _ZNSt8_Rb_treeIxSt4pairIKxPN5stxxl10disk_queueEESt10_Select1stIS5_ESt4lessIxESaIS5_EE9_M_insertEPSt18_Rb_tree_node_baseSD_RKS5_@Base 0.9 _ZNSt8_Rb_treeIxSt4pairIKxxESt10_Select1stIS2_ESt4lessIxESaIS2_EE16_M_insert_uniqueERKS2_@Base 0.9 _ZNSt8_Rb_treeIxSt4pairIKxxESt10_Select1stIS2_ESt4lessIxESaIS2_EE16_M_insert_uniqueESt17_Rb_tree_iteratorIS2_ERKS2_@Base 0.9 _ZNSt8_Rb_treeIxSt4pairIKxxESt10_Select1stIS2_ESt4lessIxESaIS2_EE8_M_eraseEPSt13_Rb_tree_nodeIS2_E@Base 0.9 _ZNSt8_Rb_treeIxSt4pairIKxxESt10_Select1stIS2_ESt4lessIxESaIS2_EE9_M_insertEPSt18_Rb_tree_node_baseSA_RKS2_@Base 0.9 _ZSt13__adjust_heapIN9__gnu_cxx17__normal_iteratorIPN5stxxl9sim_eventESt6vectorIS3_SaIS3_EEEElS3_NS2_13sim_event_cmpEEvT_T0_SB_T1_T2_@Base 0.9 _ZSt16__merge_adaptiveIPSt4pairIiiElS2_N5stxxl14write_time_cmpEEvT_S5_S5_T0_S6_T1_S6_T2_@Base 0.9 _ZSt16__merge_backwardIPSt4pairIiiES2_S2_N5stxxl14write_time_cmpEET1_T_S6_T0_S7_S5_T2_@Base 0.9 _ZSt17__merge_sort_loopIPSt4pairIiiES2_lN5stxxl14write_time_cmpEEvT_S5_T0_T1_T2_@Base 0.9 _ZSt17__rotate_adaptiveIPSt4pairIiiES2_lET_S3_S3_S3_T1_S4_T0_S4_@Base 0.9 _ZSt21__inplace_stable_sortIPSt4pairIiiEN5stxxl14write_time_cmpEEvT_S5_T0_@Base 0.9 _ZSt22__merge_without_bufferIPSt4pairIiiElN5stxxl14write_time_cmpEEvT_S5_S5_T0_S6_T1_@Base 0.9 _ZSt22__stable_sort_adaptiveIPSt4pairIiiES2_lN5stxxl14write_time_cmpEEvT_S5_T0_T1_T2_@Base 0.9 _ZSt24__merge_sort_with_bufferIPSt4pairIiiES2_N5stxxl14write_time_cmpEEvT_S5_T0_T1_@Base 0.9 _ZSt3decRSt8ios_base@Base 0.9 _ZSt3hexRSt8ios_base@Base 0.9 _ZSt8__rotateIPSt4pairIiiEEvT_S3_S3_St26random_access_iterator_tag@Base 0.9 _ZTIN5stxxl11FileCreatorE@Base 0.9 _ZTIN5stxxl12DiskGeometryE@Base 0.9 _ZTIN5stxxl12mmap_requestE@Base 0.9 _ZTIN5stxxl12syscall_fileE@Base 0.9 _ZTIN5stxxl13sim_disk_fileE@Base 0.9 _ZTIN5stxxl13ufs_file_baseE@Base 0.9 _ZTIN5stxxl14IC35L080AVVA07E@Base 0.9 _ZTIN5stxxl14resource_errorE@Base 1.0 _ZTIN5stxxl15syscall_requestE@Base 0.9 _ZTIN5stxxl16sim_disk_requestE@Base 0.9 _ZTIN5stxxl16ufs_request_baseE@Base 0.9 _ZTIN5stxxl4fileE@Base 0.9 _ZTIN5stxxl7requestE@Base 0.9 _ZTIN5stxxl8io_errorE@Base 1.0 _ZTIN5stxxl9mmap_fileE@Base 0.9 _ZTSN5stxxl11FileCreatorE@Base 0.9 _ZTSN5stxxl12DiskGeometryE@Base 0.9 _ZTSN5stxxl12mmap_requestE@Base 0.9 _ZTSN5stxxl12syscall_fileE@Base 0.9 _ZTSN5stxxl13sim_disk_fileE@Base 0.9 _ZTSN5stxxl13ufs_file_baseE@Base 0.9 _ZTSN5stxxl14IC35L080AVVA07E@Base 0.9 _ZTSN5stxxl14resource_errorE@Base 1.0 _ZTSN5stxxl15syscall_requestE@Base 0.9 _ZTSN5stxxl16sim_disk_requestE@Base 0.9 _ZTSN5stxxl16ufs_request_baseE@Base 0.9 _ZTSN5stxxl4fileE@Base 0.9 _ZTSN5stxxl7requestE@Base 0.9 _ZTSN5stxxl8io_errorE@Base 1.0 _ZTSN5stxxl9mmap_fileE@Base 0.9 _ZTVN5stxxl11FileCreatorE@Base 0.9 _ZTVN5stxxl12mmap_requestE@Base 0.9 _ZTVN5stxxl12syscall_fileE@Base 0.9 _ZTVN5stxxl13sim_disk_fileE@Base 0.9 _ZTVN5stxxl13ufs_file_baseE@Base 0.9 _ZTVN5stxxl14resource_errorE@Base 1.0 _ZTVN5stxxl15syscall_requestE@Base 0.9 _ZTVN5stxxl16sim_disk_requestE@Base 0.9 _ZTVN5stxxl16ufs_request_baseE@Base 0.9 _ZTVN5stxxl4fileE@Base 0.9 _ZTVN5stxxl7requestE@Base 0.9 _ZTVN5stxxl8io_errorE@Base 1.0 _ZTVN5stxxl9mmap_fileE@Base 0.9 stxxl-1.3.1/lib/Makefile.common0000644000175000017500000000217211535563072016220 0ustar andreasandreasSOVERSION = 1 LIBVERSION = 1.3.1 LIB_OBJECTS = \ ../io/iostats.$(LIBOBJEXT) \ ../io/request.$(LIBOBJEXT) \ ../io/request_with_state.$(LIBOBJEXT) \ ../io/request_with_waiters.$(LIBOBJEXT) \ ../io/serving_request.$(LIBOBJEXT) \ ../io/request_queue_impl_worker.$(LIBOBJEXT) \ ../io/request_queue_impl_qwqr.$(LIBOBJEXT) \ ../io/request_queue_impl_1q.$(LIBOBJEXT) \ ../io/disk_queued_file.$(LIBOBJEXT) \ ../io/ufs_file_base.$(LIBOBJEXT) \ ../io/syscall_file.$(LIBOBJEXT) \ ../io/wfs_file_base.$(LIBOBJEXT) \ ../io/wincall_file.$(LIBOBJEXT) \ ../io/boostfd_file.$(LIBOBJEXT) \ ../io/mem_file.$(LIBOBJEXT) \ ../io/fileperblock_file.$(LIBOBJEXT) \ ../io/wbtl_file.$(LIBOBJEXT) \ ../io/create_file.$(LIBOBJEXT) \ ../mng/config.$(LIBOBJEXT) \ ../mng/mng.$(LIBOBJEXT) \ ../mng/diskallocator.$(LIBOBJEXT) \ ../algo/async_schedule.$(LIBOBJEXT) \ ../common/rand.$(LIBOBJEXT) \ ../common/seed.$(LIBOBJEXT) \ ../common/exithandler.$(LIBOBJEXT) \ ../common/verbose.$(LIBOBJEXT) \ ../common/log.$(LIBOBJEXT) \ ../common/version.$(LIBOBJEXT) LIB_OBJECTS_NON_MSVC = \ ../io/mmap_file.$(LIBOBJEXT) \ ../io/simdisk_file.$(LIBOBJEXT) stxxl-1.3.1/lib/GNUmakefile0000644000175000017500000000162011337267220015334 0ustar andreasandreasTOPDIR ?= .. include Makefile.common all: lib LIB_OBJECTS += $(LIB_OBJECTS_NON_MSVC) # this is set to empty to prevent triggering recompilation while building in libs/ EXTRA_DEPS_COMPILE ?= include $(TOPDIR)/Makefile.subdir.gnu # do not recompile missing object files here COMPILE_STXXL = false "can't build $@ from lib/" lib: lib$(LIBNAME).$(LIBEXT) lib$(LIBNAME).$(LIBEXT): $(LIB_OBJECTS) $(DEPS_MAKEFILES) $(RM) $@ ifeq ($(strip $(ENABLE_SHARED)),yes) $(RM) $@.* # build shared library $(LINKER) -shared -Wl,-soname=lib$(LIBNAME).so.$(SOVERSION) -lpthread -o lib$(LIBNAME).so.$(LIBVERSION) $(LIB_OBJECTS) ln -sf lib$(LIBNAME).so.$(LIBVERSION) lib$(LIBNAME).so.$(SOVERSION) ln -sf lib$(LIBNAME).so.$(SOVERSION) lib$(LIBNAME).so else # build static library $(LIBGEN) lib$(LIBNAME).$(LIBEXT) $(LIB_OBJECTS) endif clean:: $(RM) lib$(LIBNAME).$(LIBEXT) $(RM) lib$(LIBNAME).$(strip $(LIBEXT)).* stxxl-1.3.1/lib/Makefile0000644000175000017500000000037011430772657014734 0ustar andreasandreasinclude Makefile.common include ../make.settings all: lib tests: lib: lib$(LIBNAME).$(LIBEXT) lib$(LIBNAME).$(LIBEXT): $(LIB_OBJECTS) del lib$(LIBNAME).$(LIBEXT) $(LIBGEN)lib$(LIBNAME).$(LIBEXT) $(LIB_OBJECTS) clean: $(RM) $(CLEAN_TARGETS) stxxl-1.3.1/INSTALL0000644000175000017500000000216411323316604013545 0ustar andreasandreasBASIC INFORMATION For detailed installation instructions, including instruction for installation in a Windows based environment and application compilation hints (including an example Makefile) please read the online manual: http://stxxl.sourceforge.net/ QUICK INSTALLATION INSTRUCTIONS FOR POSIX COMPATIBLE SYSTEMS * Extract the tarball and change into the stxxl root directory. * Adjust make.settings.gnu (or create make.settings.local and set the override values there) to match your local setup, especially consider the following variables: - STXXL_ROOT: the absolute path to the extracted STXXL sources - USE_BOOST and BOOST_ROOT: if you want to use the Boost libraries - MCSTL_ROOT: if you want to use the MCSTL library - COMPILER: if you want to use a non-default compiler * Compile the library: - non-parallel: make library_g++ - with mcstl: make library_g++_mcstl - with parallel mode: make library_g++_pmode * Compile the test programs (optional) - non-parallel: make tests_g++ - with mcstl: make tests_g++_mcstl - with parallel mode: make tests_g++_pmode stxxl-1.3.1/Makefile0000644000175000017500000001076011513611117014153 0ustar andreasandreas# This -*- Makefile -*- gets processed with both GNU make and nmake. # So keep it simple and compatible. ############################################################################ # Makefile # # Part of the STXXL. See http://stxxl.sourceforge.net # # Copyright (C) 2002-2007 Roman Dementiev # Copyright (C) 2006 Johannes Singler # Copyright (C) 2007-2010 Andreas Beckmann # # Distributed under the Boost Software License, Version 1.0. # (See accompanying file LICENSE_1_0.txt or copy at # http://www.boost.org/LICENSE_1_0.txt) ############################################################################ usage: @echo "Choose one of the goals:" @echo " config_gnu" @echo " library_g++ library_g++_pmode library_g++_mcstl library_icpc library_icpc_mcstl library_msvc" @echo " tests_g++ tests_g++_pmode tests_g++_mcstl tests_icpc tests_icpc_mcstl tests_msvc" @echo " clean_g++ clean_g++_pmode clean_g++_mcstl clean_icpc clean_icpc_mcstl clean_msvc" @echo " doxy clean_doxy tutorial clean_tutorial examples clean_examples" settings_gnu: cmp -s make.settings.gnu make.settings || \ ( $(RM) make.settings && cp make.settings.gnu make.settings ) settings_msvc: make.settings make.settings: make.settings.msvc copy make.settings.msvc make.settings config_gnu: settings_gnu $(MAKE) -f Makefile.gnu config STXXL_AUTOCONFIG=true _library_g++: settings_gnu $(MAKE) -f Makefile.gnu library library_g++: _library_g++ $(MAKE) -f Makefile.gnu library_utils USE_PMODE=no USE_MCSTL=no library_g++_pmode: _library_g++ $(MAKE) -f Makefile.gnu library_utils USE_PMODE=yes USE_MCSTL=no library_g++_mcstl: _library_g++ $(MAKE) -f Makefile.gnu library_utils USE_PMODE=no USE_MCSTL=yes _library_icpc: settings_gnu $(MAKE) -f Makefile.gnu library USE_ICPC=yes library_icpc: _library_icpc $(MAKE) -f Makefile.gnu library_utils USE_PMODE=no USE_MCSTL=no USE_ICPC=yes library_icpc_pmode: _library_icpc $(MAKE) -f Makefile.gnu library_utils USE_PMODE=yes USE_MCSTL=no USE_ICPC=yes library_icpc_mcstl: _library_icpc $(MAKE) -f Makefile.gnu library_utils USE_PMODE=no USE_MCSTL=yes USE_ICPC=yes library_msvc: settings_msvc nmake /NOLOGO /F Makefile.msvc library tests_g++: library_g++ $(MAKE) -f Makefile.gnu tests USE_PMODE=no USE_MCSTL=no tests_g++_pmode: library_g++_pmode $(MAKE) -f Makefile.gnu tests USE_PMODE=yes USE_MCSTL=no tests_g++_mcstl: library_g++_mcstl $(MAKE) -f Makefile.gnu tests USE_PMODE=no USE_MCSTL=yes tests_icpc: library_icpc $(MAKE) -f Makefile.gnu tests USE_PMODE=no USE_MCSTL=no USE_ICPC=yes tests_icpc_pmode: library_icpc_pmode $(MAKE) -f Makefile.gnu tests USE_PMODE=yes USE_MCSTL=no USE_ICPC=yes tests_icpc_mcstl: library_icpc_mcstl $(MAKE) -f Makefile.gnu tests USE_PMODE=no USE_MCSTL=yes USE_ICPC=yes tests_msvc: settings_msvc nmake /NOLOGO /F Makefile.msvc tests clean_g++: settings_gnu $(MAKE) -f Makefile.gnu clean USE_PMODE=no USE_MCSTL=no clean_g++_pmode: settings_gnu -$(MAKE) -f Makefile.gnu clean USE_PMODE=yes USE_MCSTL=no clean_g++_mcstl: settings_gnu -$(MAKE) -f Makefile.gnu clean USE_PMODE=no USE_MCSTL=yes clean_icpc: settings_gnu $(MAKE) -f Makefile.gnu clean USE_PMODE=no USE_MCSTL=no USE_ICPC=yes clean_icpc_pmode: settings_gnu -$(MAKE) -f Makefile.gnu clean USE_PMODE=yes USE_MCSTL=no USE_ICPC=yes clean_icpc_mcstl: settings_gnu -$(MAKE) -f Makefile.gnu clean USE_PMODE=no USE_MCSTL=yes USE_ICPC=yes clean_msvc: settings_msvc nmake /NOLOGO /F Makefile.msvc clean clean: clean_g++ clean_g++_mcstl clean_icpc clean_icpc_mcstl $(MAKE) -C test/compile-stxxl-headers clean distclean: clean_doxy clean_tutorial clean_examples clean $(RM) make.settings $(RM) stxxl.log stxxl.errlog $(RM) algo/stxxl.log algo/stxxl.errlog $(RM) common/stxxl.log common/stxxl.errlog $(RM) containers/stxxl.log containers/stxxl.errlog $(RM) io/stxxl.log io/stxxl.errlog $(RM) mng/stxxl.log mng/stxxl.errlog $(RM) stream/stxxl.log stream/stxxl.errlog $(RM) utils/stxxl.log utils/stxxl.errlog doxy: Doxyfile doxygen clean_doxy: $(RM) -r doc/doxy $(RM) Doxyfile.bak tutorial: $(MAKE) -C doc/tutorial clean_tutorial: $(MAKE) -C doc/tutorial distclean examples: $(MAKE) -C doc/tutorial/examples clean_examples: $(MAKE) -C doc/tutorial/examples clean count: sloccount --addlang makefile . # optional parameters: # DATE="" if you *don't* want a -YYYYMMDD in the version # PHASE=snapshot|alpha#|beta#|rc#|release (defaults to snapshot) release: $(MAKE) -f Makefile.gnu release stxxl-1.3.1/test/0000755000175000017500000000000011536252420013471 5ustar andreasandreasstxxl-1.3.1/test/compile-stxxl-headers/0000755000175000017500000000000011536252420017712 5ustar andreasandreasstxxl-1.3.1/test/compile-stxxl-headers/Makefile0000644000175000017500000000425011535120571021353 0ustar andreasandreas############################################################################ # test/compile-stxxl-headers/Makefile # # Part of the STXXL. See http://stxxl.sourceforge.net # # Copyright (C) 2007 Andreas Beckmann # # Distributed under the Boost Software License, Version 1.0. # (See accompanying file LICENSE_1_0.txt or copy at # http://www.boost.org/LICENSE_1_0.txt) ############################################################################ INSTANCE ?= stxxl INSTANCE ?= pmstxxl INSTANCE ?= mcstxxl TOPDIR ?= ../.. include $(TOPDIR)/make.settings -include $(TOPDIR)/$(INSTANCE).mk CXX = $(STXXL_CXX) OPT = -O3 WARNINGS = $(STXXL_WARNFLAGS) DEBUG = $(STXXL_DEBUGFLAGS) CPPFLAGS += -I$(TOPDIR)/include CPPFLAGS += $(STXXL_CPPFLAGS) CPPFLAGS += $(OPT) $(DEBUG) $(WARNINGS) CPPFLAGS += -MD STXXL_MAIN_HEADER += stxxl.h STXXL_HEADERS += all STXXL_HEADERS += vector stack queue priority_queue deque map STXXL_HEADERS += algorithm scan sort ksort stable_ksort random_shuffle STXXL_HEADERS += io mng stream STXXL_HEADERS += random timer mallocstats aligned_alloc types stats STXXL_BITS += $(HEADER_FILES_BITS) STXXL_BITS += $(HEADER_FILES_COMMON:%=common/%) STXXL_BITS += $(HEADER_FILES_COMPAT:%=compat/%) STXXL_BITS += $(HEADER_FILES_IO:%=io/%) STXXL_BITS += $(HEADER_FILES_MNG:%=mng/%) STXXL_BITS += $(HEADER_FILES_CONTAINERS:%=containers/%) STXXL_BITS += $(HEADER_FILES_CONTAINERS_BTREE:%=containers/btree/%) STXXL_BITS += $(HEADER_FILES_ALGO:%=algo/%) STXXL_BITS += $(HEADER_FILES_STREAM:%=stream/%) STXXL_BITS += $(HEADER_FILES_UTILS:%=utils/%) HEADERS = $(STXXL_MAIN_HEADER) $(STXXL_HEADERS:%=stxxl/%) $(STXXL_BITS:%=stxxl/bits/%) HEADERS_ESCAPED = $(subst /,~,$(HEADERS)) #all: preprocess-test all: compile-test preprocess-test: $(HEADERS_ESCAPED:%=test-header-%.$(INSTANCE).ii) compile-test: $(HEADERS_ESCAPED:%=test-header-%.$(INSTANCE).o) test-header-%.th.cpp:: echo '#include "$(subst ~,/,$*)"' > $@ %.$(INSTANCE).ii: %.th.cpp $(CXX) $(CPPFLAGS) -E $< -o $@ %.$(INSTANCE).o: %.th.cpp $(wildcard ../../$(INSTANCE).mk) $(COMPILE.cc) $(OUTPUT_OPTION) $< clean: $(RM) *.ii *.o *.d *.dT $(RM) test-header-*.cpp .SECONDARY: -include *.d stxxl-1.3.1/test/WinGUI/0000755000175000017500000000000011536252421014574 5ustar andreasandreasstxxl-1.3.1/test/WinGUI/stdafx.h0000644000175000017500000000354510631532342016243 0ustar andreasandreas// stdafx.h : include file for standard system include files, // or project specific include files that are used frequently, // but are changed infrequently #pragma once #ifndef VC_EXTRALEAN #define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers #endif // Modify the following defines if you have to target a platform prior to the ones specified below. // Refer to MSDN for the latest info on corresponding values for different platforms. #ifndef WINVER // Allow use of features specific to Windows 95 and Windows NT 4 or later. #define WINVER 0x0400 // Change this to the appropriate value to target Windows 98 and Windows 2000 or later. #endif #ifndef _WIN32_WINNT // Allow use of features specific to Windows NT 4 or later. #define _WIN32_WINNT 0x0400 // Change this to the appropriate value to target Windows 98 and Windows 2000 or later. #endif #ifndef _WIN32_WINDOWS // Allow use of features specific to Windows 98 or later. #define _WIN32_WINDOWS 0x0410 // Change this to the appropriate value to target Windows Me or later. #endif #ifndef _WIN32_IE // Allow use of features specific to IE 4.0 or later. #define _WIN32_IE 0x0400 // Change this to the appropriate value to target IE 5.0 or later. #endif #define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // some CString constructors will be explicit // turns off MFC's hiding of some common and often safely ignored warning messages #define _AFX_ALL_WARNINGS #include // MFC core and standard components #include // MFC extensions #include // MFC support for Internet Explorer 4 Common Controls #ifndef _AFX_NO_AFXCMN_SUPPORT #include // MFC support for Windows Common Controls #endif // _AFX_NO_AFXCMN_SUPPORT stxxl-1.3.1/test/WinGUI/WinGUIDlg.h0000644000175000017500000000247010631532342016477 0ustar andreasandreas// WinGUIDlg.h : header file // #pragma once // CWinGUIDlg dialog class CWinGUIDlg : public CDialog { // Construction public: CWinGUIDlg(CWnd * pParent = NULL); // standard constructor // Dialog Data enum { IDD = IDD_WINGUI_DIALOG }; protected: virtual void DoDataExchange(CDataExchange * pDX); // DDX/DDV support // Implementation protected: HICON m_hIcon; // Generated message map functions virtual BOOL OnInitDialog(); afx_msg void OnSysCommand(UINT nID, LPARAM lParam); afx_msg void OnPaint(); afx_msg HCURSOR OnQueryDragIcon(); DECLARE_MESSAGE_MAP() public: afx_msg void OnBnClickedCancel(); afx_msg void OnBnClickedOk(); CString m_Filename; BOOL m_Format1; LONGLONG m_Filesize; int m_Key; DWORD m_MemUsage; afx_msg void OnBnClickedFilenamebutton(); afx_msg void OnBnClickedFillrandombutton(); long m_FilesizeMB; afx_msg void OnEnUpdateFilesizeedit(); // afx_msg void OnEnChangeFilesizeedit(); afx_msg void OnBnClickedFillvaluebutton(); afx_msg void OnBnClickedSortascbutton(); afx_msg void OnBnClickedSortdescbutton4(); afx_msg void OnBnClickedCheckascbutton(); afx_msg void OnBnClickedCheckdescbutton(); afx_msg void OnBnClickedRemduplbutton(); // afx_msg void OnBnClickedCheckduplbutton(); }; stxxl-1.3.1/test/WinGUI/Release/0000755000175000017500000000000011536252420016153 5ustar andreasandreasstxxl-1.3.1/test/WinGUI/WinGUI.cpp0000644000175000017500000000350310631532342016401 0ustar andreasandreas// WinGUI.cpp : Defines the class behaviors for the application. // #include "stdafx.h" #include "WinGUI.h" #include "WinGUIDlg.h" #ifdef _DEBUG #define new DEBUG_NEW #endif // CWinGUIApp BEGIN_MESSAGE_MAP(CWinGUIApp, CWinApp) ON_COMMAND(ID_HELP, CWinApp::OnHelp) END_MESSAGE_MAP() // CWinGUIApp construction CWinGUIApp::CWinGUIApp() { // TODO: add construction code here, // Place all significant initialization in InitInstance } // The one and only CWinGUIApp object CWinGUIApp theApp; // CWinGUIApp initialization BOOL CWinGUIApp::InitInstance() { // InitCommonControls() is required on Windows XP if an application // manifest specifies use of ComCtl32.dll version 6 or later to enable // visual styles. Otherwise, any window creation will fail. InitCommonControls(); CWinApp::InitInstance(); // Standard initialization // If you are not using these features and wish to reduce the size // of your final executable, you should remove from the following // the specific initialization routines you do not need // Change the registry key under which our settings are stored // TODO: You should modify this string to be something appropriate // such as the name of your company or organization SetRegistryKey(_T("Local AppWizard-Generated Applications")); CWinGUIDlg dlg; m_pMainWnd = &dlg; INT_PTR nResponse = dlg.DoModal(); if (nResponse == IDOK) { // TODO: Place code here to handle when the dialog is // dismissed with OK } else if (nResponse == IDCANCEL) { // TODO: Place code here to handle when the dialog is // dismissed with Cancel } // Since the dialog has been closed, return FALSE so that we exit the // application, rather than start the application's message pump. return FALSE; } stxxl-1.3.1/test/WinGUI/WorkDialog.cpp0000644000175000017500000000336210631532342017344 0ustar andreasandreas// WorkDialog.cpp : implementation file // #include "stdafx.h" #include "WinGUI.h" #include "WorkDialog.h" #include ".\workdialog.h" // CWorkDialog dialog IMPLEMENT_DYNAMIC(CWorkDialog, CDialog) CWorkDialog::CWorkDialog(CWnd * pParent /*=NULL*/) : CDialog(CWorkDialog::IDD, pParent) , m_Message(_T("Working ...")), thread(NULL) { } CWorkDialog::~CWorkDialog() { } void CWorkDialog::DoDataExchange(CDataExchange * pDX) { CDialog::DoDataExchange(pDX); DDX_Text(pDX, IDC_MESSAGE1, m_Message); } BEGIN_MESSAGE_MAP(CWorkDialog, CDialog) ON_BN_CLICKED(IDOK, OnBnClickedOk) ON_BN_CLICKED(IDCANCEL, OnBnClickedCancel) ON_MESSAGE(WM_WORK_THREAD_FINISHED, OnThreadFinished) ON_WM_CREATE() ON_WM_TIMER() END_MESSAGE_MAP() // CWorkDialog message handlers void CWorkDialog::OnBnClickedOk() { // TODO: Add your control notification handler code here //OnOK(); } void CWorkDialog::OnBnClickedCancel() { // TODO: Add your control notification handler code here //OnCancel(); } afx_msg LRESULT CWorkDialog::OnThreadFinished(WPARAM wparam, LPARAM lparam) { EndDialog(IDOK); return 0; } void CWorkDialog::SetThread(CWinThread * thread_) { thread = thread_; } int CWorkDialog::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CDialog::OnCreate(lpCreateStruct) == -1) return -1; ASSERT(thread); thread->CreateThread(); SetTimer(WORK_TIMER_ID, 400, NULL); return 0; } void CWorkDialog::OnTimer(UINT nIDEvent) { // TODO: Add your message handler code here and/or call default if (nIDEvent == WORK_TIMER_ID) { if (m_Message == "") m_Message = "Working ..."; else m_Message = ""; UpdateData(FALSE); } CDialog::OnTimer(nIDEvent); } stxxl-1.3.1/test/WinGUI/WinGUI.aps0000644000175000017500000016717010275653004016420 0ustar andreasandreas #$HWBTc:\stxxl\test\WinGUI\WinGUI.rc@$HWB0 !!resource.hIDR_MAINFRAME128IDM_ABOUTBOX0x0010IDD_ABOUTBOX100IDS_ABOUTBOX101IDD_WINGUI_DIALOG102 IDR_MANIFESTCREATEPROCESS_MANIFEST_RESOURCE_ID _APS_NEXT_RESOURCE_VALUE129_APS_NEXT_CONTROL_VALUE1000_APS_NEXT_SYMED_VALUE101_APS_NEXT_COMMAND_VALUE32771!!afxres.h!winres.hVS_VERSION_INFO1IDC_STATIC(-1))!CBRS_ALIGN_LEFT0x1000L/CBRS_ALIGN_TOP0x2000L0CBRS_ALIGN_RIGHT0x4000L1CBRS_ALIGN_BOTTOM0x8000L2CBRS_ALIGN_ANY0xF000L3CBRS_BORDER_LEFT0x0100L5CBRS_BORDER_TOP0x0200L6CBRS_BORDER_RIGHT0x0400L7CBRS_BORDER_BOTTOM0x0800L8CBRS_BORDER_ANY0x0F00L9CBRS_TOOLTIPS0x0010L;CBRS_FLYBY0x0020L<CBRS_FLOAT_MULTI0x0040L=CBRS_BORDER_3D0x0080L>CBRS_HIDE_INPLACE0x0008L?CBRS_SIZE_DYNAMIC0x0004L@CBRS_SIZE_FIXED0x0002LACBRS_FLOATING0x0001LBCBRS_GRIPPER0x00400000LDCBRS_ORIENT_HORZ(CBRS_ALIGN_TOP|CBRS_ALIGN_BOTTOM)FCBRS_ORIENT_VERT(CBRS_ALIGN_LEFT|CBRS_ALIGN_RIGHT)GCBRS_ORIENT_ANY(CBRS_ORIENT_HORZ|CBRS_ORIENT_VERT)HCBRS_ALL0x0040FFFFLJCBRS_NOALIGN0x00000000LOCBRS_LEFT(CBRS_ALIGN_LEFT|CBRS_BORDER_RIGHT)PCBRS_TOP(CBRS_ALIGN_TOP|CBRS_BORDER_BOTTOM)QCBRS_RIGHT(CBRS_ALIGN_RIGHT|CBRS_BORDER_LEFT)RCBRS_BOTTOM(CBRS_ALIGN_BOTTOM|CBRS_BORDER_TOP)SID_INDICATOR_EXT0xE700YID_INDICATOR_CAPS0xE701ZID_INDICATOR_NUM0xE702[ID_INDICATOR_SCRL0xE703\ID_INDICATOR_OVR0xE704]ID_INDICATOR_REC0xE705^ID_INDICATOR_KANA0xE706_ID_SEPARATOR0aAFX_IDS_APP_TITLE0xE000AFX_IDS_IDLEMESSAGE0xE001AFX_IDS_HELPMODEMESSAGE0xE002AFX_IDS_APP_TITLE_EMBEDDING0xE003AFX_IDS_COMPANY_NAME0xE004AFX_IDS_OBJ_TITLE_INPLACE0xE005ID_FILE_NEW0xE100ID_FILE_OPEN0xE101ID_FILE_CLOSE0xE102ID_FILE_SAVE0xE103ID_FILE_SAVE_AS0xE104ID_FILE_PAGE_SETUP0xE105ID_FILE_PRINT_SETUP0xE106ID_FILE_PRINT0xE107ID_FILE_PRINT_DIRECT0xE108ID_FILE_PRINT_PREVIEW0xE109ID_FILE_UPDATE0xE10AID_FILE_SAVE_COPY_AS0xE10BID_FILE_SEND_MAIL0xE10CID_FILE_NEW_FRAME0xE10DID_FILE_MRU_FIRST0xE110ID_FILE_MRU_FILE10xE110ID_FILE_MRU_FILE20xE111ID_FILE_MRU_FILE30xE112ID_FILE_MRU_FILE40xE113ID_FILE_MRU_FILE50xE114ID_FILE_MRU_FILE60xE115ID_FILE_MRU_FILE70xE116ID_FILE_MRU_FILE80xE117ID_FILE_MRU_FILE90xE118ID_FILE_MRU_FILE100xE119ID_FILE_MRU_FILE110xE11AID_FILE_MRU_FILE120xE11BID_FILE_MRU_FILE130xE11CID_FILE_MRU_FILE140xE11DID_FILE_MRU_FILE150xE11EID_FILE_MRU_FILE160xE11FID_FILE_MRU_LAST0xE11FID_EDIT_CLEAR0xE120ID_EDIT_CLEAR_ALL0xE121ID_EDIT_COPY0xE122ID_EDIT_CUT0xE123ID_EDIT_FIND0xE124ID_EDIT_PASTE0xE125ID_EDIT_PASTE_LINK0xE126ID_EDIT_PASTE_SPECIAL0xE127ID_EDIT_REPEAT0xE128ID_EDIT_REPLACE0xE129ID_EDIT_SELECT_ALL0xE12AID_EDIT_UNDO0xE12BID_EDIT_REDO0xE12CID_WINDOW_NEW0xE130ID_WINDOW_ARRANGE0xE131ID_WINDOW_CASCADE0xE132ID_WINDOW_TILE_HORZ0xE133ID_WINDOW_TILE_VERT0xE134ID_WINDOW_SPLIT0xE135ID_APP_ABOUT0xE140ID_APP_EXIT0xE141ID_HELP_INDEX0xE142ID_HELP_FINDER0xE143ID_HELP_USING0xE144ID_CONTEXT_HELP0xE145ID_HELP0xE146ID_DEFAULT_HELP0xE147ID_NEXT_PANE0xE150ID_PREV_PANE0xE151ID_FORMAT_FONT0xE160ID_OLE_INSERT_NEW0xE200ID_OLE_EDIT_LINKS0xE201ID_OLE_EDIT_CONVERT0xE202ID_OLE_EDIT_CHANGE_ICON0xE203ID_OLE_EDIT_PROPERTIES0xE204ID_OLE_VERB_FIRST0xE210AFX_ID_PREVIEW_CLOSE0xE300AFX_ID_PREVIEW_NUMPAGE0xE301AFX_ID_PREVIEW_NEXT0xE302AFX_ID_PREVIEW_PREV0xE303AFX_ID_PREVIEW_PRINT0xE304AFX_ID_PREVIEW_ZOOMIN0xE305AFX_ID_PREVIEW_ZOOMOUT0xE306ID_VIEW_TOOLBAR0xE800ID_VIEW_STATUS_BAR0xE801 ID_VIEW_REBAR0xE804 ID_VIEW_AUTOARRANGE0xE805 ID_VIEW_SMALLICON0xE810 ID_VIEW_LARGEICON0xE811ID_VIEW_LIST0xE812ID_VIEW_DETAILS0xE813ID_VIEW_LINEUP0xE814ID_VIEW_BYNAME0xE815AFX_ID_VIEW_MINIMUMID_VIEW_SMALLICONAFX_ID_VIEW_MAXIMUMID_VIEW_BYNAMEID_RECORD_FIRST0xE900ID_RECORD_LAST0xE901ID_RECORD_NEXT0xE902ID_RECORD_PREV0xE903IDC_STATIC(-1)#AFX_IDS_SCSIZE0xEF00,AFX_IDS_SCMOVE0xEF01-AFX_IDS_SCMINIMIZE0xEF02.AFX_IDS_SCMAXIMIZE0xEF03/AFX_IDS_SCNEXTWINDOW0xEF040AFX_IDS_SCPREVWINDOW0xEF051AFX_IDS_SCCLOSE0xEF062AFX_IDS_SCRESTORE0xEF123AFX_IDS_SCTASKLIST0xEF134AFX_IDS_MDICHILD0xEF1F6AFX_IDS_DESKACCESSORY0xEFDA8AFX_IDS_OPENFILE0xF000;AFX_IDS_SAVEFILE0xF001<AFX_IDS_ALLFILTER0xF002=AFX_IDS_UNTITLED0xF003>AFX_IDS_SAVEFILECOPY0xF004?AFX_IDS_PREVIEW_CLOSE0xF005@AFX_IDS_UNNAMED_FILE0xF006AAFX_IDS_HIDE0xF011BAFX_IDP_NO_ERROR_AVAILABLE0xF020EAFX_IDS_NOT_SUPPORTED_EXCEPTION0xF021FAFX_IDS_RESOURCE_EXCEPTION0xF022GAFX_IDS_MEMORY_EXCEPTION0xF023HAFX_IDS_USER_EXCEPTION0xF024IAFX_IDS_INVALID_ARG_EXCEPTION0xF025JAFX_IDS_PRINTONPORT0xF040MAFX_IDS_ONEPAGE0xF041NAFX_IDS_TWOPAGE0xF042OAFX_IDS_PRINTPAGENUM0xF043PAFX_IDS_PREVIEWPAGEDESC0xF044QAFX_IDS_PRINTDEFAULTEXT0xF045RAFX_IDS_PRINTDEFAULT0xF046SAFX_IDS_PRINTFILTER0xF047TAFX_IDS_PRINTCAPTION0xF048UAFX_IDS_PRINTTOFILE0xF049VAFX_IDS_OBJECT_MENUITEM0xF080ZAFX_IDS_EDIT_VERB0xF081[AFX_IDS_ACTIVATE_VERB0xF082\AFX_IDS_CHANGE_LINK0xF083]AFX_IDS_AUTO0xF084^AFX_IDS_MANUAL0xF085_AFX_IDS_FROZEN0xF086`AFX_IDS_ALL_FILES0xF087aAFX_IDS_SAVE_MENU0xF088cAFX_IDS_UPDATE_MENU0xF089dAFX_IDS_SAVE_AS_MENU0xF08AeAFX_IDS_SAVE_COPY_AS_MENU0xF08BfAFX_IDS_EXIT_MENU0xF08CgAFX_IDS_UPDATING_ITEMS0xF08DhAFX_IDS_METAFILE_FORMAT0xF08EjAFX_IDS_DIB_FORMAT0xF08FkAFX_IDS_BITMAP_FORMAT0xF090lAFX_IDS_LINKSOURCE_FORMAT0xF091mAFX_IDS_EMBED_FORMAT0xF092nAFX_IDS_PASTELINKEDTYPE0xF094pAFX_IDS_UNKNOWNTYPE0xF095qAFX_IDS_RTF_FORMAT0xF096rAFX_IDS_TEXT_FORMAT0xF097sAFX_IDS_INVALID_CURRENCY0xF098uAFX_IDS_INVALID_DATETIME0xF099vAFX_IDS_INVALID_DATETIMESPAN0xF09AwAFX_IDP_INVALID_FILENAME0xF100zAFX_IDP_FAILED_TO_OPEN_DOC0xF101{AFX_IDP_FAILED_TO_SAVE_DOC0xF102|AFX_IDP_ASK_TO_SAVE0xF103}AFX_IDP_FAILED_TO_CREATE_DOC0xF104~AFX_IDP_FILE_TOO_LARGE0xF105AFX_IDP_FAILED_TO_START_PRINT0xF106AFX_IDP_FAILED_TO_LAUNCH_HELP0xF107AFX_IDP_INTERNAL_FAILURE0xF108AFX_IDP_COMMAND_FAILURE0xF109AFX_IDP_FAILED_MEMORY_ALLOC0xF10AAFX_IDP_UNREG_DONE0xF10BAFX_IDP_UNREG_FAILURE0xF10CAFX_IDP_DLL_LOAD_FAILED0xF10DAFX_IDP_DLL_BAD_VERSION0xF10EAFX_IDP_PARSE_INT0xF110AFX_IDP_PARSE_REAL0xF111AFX_IDP_PARSE_INT_RANGE0xF112AFX_IDP_PARSE_REAL_RANGE0xF113AFX_IDP_PARSE_STRING_SIZE0xF114AFX_IDP_PARSE_RADIO_BUTTON0xF115AFX_IDP_PARSE_BYTE0xF116AFX_IDP_PARSE_UINT0xF117AFX_IDP_PARSE_DATETIME0xF118AFX_IDP_PARSE_CURRENCY0xF119AFX_IDP_PARSE_GUID0xF11AAFX_IDP_PARSE_TIME0xF11BAFX_IDP_PARSE_DATE0xF11CAFX_IDP_FAILED_INVALID_FORMAT0xF120AFX_IDP_FAILED_INVALID_PATH0xF121AFX_IDP_FAILED_DISK_FULL0xF122AFX_IDP_FAILED_ACCESS_READ0xF123AFX_IDP_FAILED_ACCESS_WRITE0xF124AFX_IDP_FAILED_IO_ERROR_READ0xF125AFX_IDP_FAILED_IO_ERROR_WRITE0xF126AFX_IDP_SCRIPT_ERROR0xF130AFX_IDP_SCRIPT_DISPATCH_EXCEPTION0xF131AFX_IDP_STATIC_OBJECT0xF180AFX_IDP_FAILED_TO_CONNECT0xF181AFX_IDP_SERVER_BUSY0xF182AFX_IDP_BAD_VERB0xF183AFX_IDS_NOT_DOCOBJECT0xF184AFX_IDP_FAILED_TO_NOTIFY0xF185AFX_IDP_FAILED_TO_LAUNCH0xF186AFX_IDP_ASK_TO_UPDATE0xF187AFX_IDP_FAILED_TO_UPDATE0xF188AFX_IDP_FAILED_TO_REGISTER0xF189AFX_IDP_FAILED_TO_AUTO_REGISTER0xF18AAFX_IDP_FAILED_TO_CONVERT0xF18BAFX_IDP_GET_NOT_SUPPORTED0xF18CAFX_IDP_SET_NOT_SUPPORTED0xF18DAFX_IDP_ASK_TO_DISCARD0xF18EAFX_IDP_FAILED_TO_CREATE0xF18FAFX_IDP_FAILED_MAPI_LOAD0xF190AFX_IDP_INVALID_MAPI_DLL0xF191AFX_IDP_FAILED_MAPI_SEND0xF192AFX_IDP_FILE_NONE0xF1A0AFX_IDP_FILE_GENERIC0xF1A1AFX_IDP_FILE_NOT_FOUND0xF1A2AFX_IDP_FILE_BAD_PATH0xF1A3AFX_IDP_FILE_TOO_MANY_OPEN0xF1A4AFX_IDP_FILE_ACCESS_DENIED0xF1A5AFX_IDP_FILE_INVALID_FILE0xF1A6AFX_IDP_FILE_REMOVE_CURRENT0xF1A7AFX_IDP_FILE_DIR_FULL0xF1A8AFX_IDP_FILE_BAD_SEEK0xF1A9AFX_IDP_FILE_HARD_IO0xF1AAAFX_IDP_FILE_SHARING0xF1ABAFX_IDP_FILE_LOCKING0xF1ACAFX_IDP_FILE_DISKFULL0xF1ADAFX_IDP_FILE_EOF0xF1AEAFX_IDP_ARCH_NONE0xF1B0AFX_IDP_ARCH_GENERIC0xF1B1AFX_IDP_ARCH_READONLY0xF1B2AFX_IDP_ARCH_ENDOFFILE0xF1B3AFX_IDP_ARCH_WRITEONLY0xF1B4AFX_IDP_ARCH_BADINDEX0xF1B5AFX_IDP_ARCH_BADCLASS0xF1B6AFX_IDP_ARCH_BADSCHEMA0xF1B7AFX_IDS_OCC_SCALEUNITS_PIXELS0xF1C0AFX_IDS_STATUS_FONT0xF230AFX_IDS_TOOLTIP_FONT0xF231AFX_IDS_UNICODE_FONT0xF232AFX_IDS_MINI_FONT0xF233AFX_IDP_SQL_CONNECT_FAIL0xF281AFX_IDP_SQL_RECORDSET_FORWARD_ONLY0xF282AFX_IDP_SQL_EMPTY_COLUMN_LIST0xF283AFX_IDP_SQL_FIELD_SCHEMA_MISMATCH0xF284AFX_IDP_SQL_ILLEGAL_MODE0xF285AFX_IDP_SQL_MULTIPLE_ROWS_AFFECTED0xF286AFX_IDP_SQL_NO_CURRENT_RECORD0xF287AFX_IDP_SQL_NO_ROWS_AFFECTED0xF288AFX_IDP_SQL_RECORDSET_READONLY0xF289AFX_IDP_SQL_SQL_NO_TOTAL0xF28AAFX_IDP_SQL_ODBC_LOAD_FAILED0xF28BAFX_IDP_SQL_DYNASET_NOT_SUPPORTED0xF28CAFX_IDP_SQL_SNAPSHOT_NOT_SUPPORTED0xF28DAFX_IDP_SQL_API_CONFORMANCE0xF28EAFX_IDP_SQL_SQL_CONFORMANCE0xF28FAFX_IDP_SQL_NO_DATA_FOUND0xF290AFX_IDP_SQL_ROW_UPDATE_NOT_SUPPORTED0xF291AFX_IDP_SQL_ODBC_V2_REQUIRED0xF292AFX_IDP_SQL_NO_POSITIONED_UPDATES0xF293AFX_IDP_SQL_LOCK_MODE_NOT_SUPPORTED0xF294AFX_IDP_SQL_DATA_TRUNCATED0xF295AFX_IDP_SQL_ROW_FETCH0xF296AFX_IDP_SQL_INCORRECT_ODBC0xF297AFX_IDP_SQL_UPDATE_DELETE_FAILED0xF298AFX_IDP_SQL_DYNAMIC_CURSOR_NOT_SUPPORTED0xF299AFX_IDP_SQL_FIELD_NOT_FOUND0xF29AAFX_IDP_SQL_BOOKMARKS_NOT_SUPPORTED0xF29BAFX_IDP_SQL_BOOKMARKS_NOT_ENABLED0xF29CAFX_IDS_DELETED0xF29DAFX_IDP_DAO_ENGINE_INITIALIZATION0xF2B0AFX_IDP_DAO_DFX_BIND0xF2B1 AFX_IDP_DAO_OBJECT_NOT_OPEN0xF2B2 AFX_IDP_DAO_ROWTOOSHORT0xF2B3AFX_IDP_DAO_BADBINDINFO0xF2B4AFX_IDP_DAO_COLUMNUNAVAILABLE0xF2B5AFX_IDS_HTTP_TITLE0xF2D1AFX_IDS_HTTP_NO_TEXT0xF2D2AFX_IDS_HTTP_BAD_REQUEST0xF2D3AFX_IDS_HTTP_AUTH_REQUIRED0xF2D4AFX_IDS_HTTP_FORBIDDEN0xF2D5AFX_IDS_HTTP_NOT_FOUND0xF2D6AFX_IDS_HTTP_SERVER_ERROR0xF2D7AFX_IDS_HTTP_NOT_IMPLEMENTED0xF2D8AFX_IDS_CHECKLISTBOX_UNCHECK0xF2E1!AFX_IDS_CHECKLISTBOX_CHECK0xF2E2"AFX_IDS_CHECKLISTBOX_MIXED0xF2E3#AFX_IDC_LISTBOX100)AFX_IDC_CHANGE101*AFX_IDC_BROWSER102+AFX_IDC_PRINT_DOCNAME201.AFX_IDC_PRINT_PRINTERNAME202/AFX_IDC_PRINT_PORTNAME2030AFX_IDC_PRINT_PAGENUM2041ID_APPLY_NOW0x30214ID_WIZBACK0x30235ID_WIZNEXT0x30246ID_WIZFINISH0x30257AFX_IDC_TAB_CONTROL0x30208AFX_IDD_NEWTYPEDLG30721KAFX_IDD_PRINTDLG30722LAFX_IDD_PREVIEW_TOOLBAR30723MAFX_IDD_INSERTOBJECT30724PAFX_IDD_CHANGEICON30725QAFX_IDD_CONVERT30726RAFX_IDD_PASTESPECIAL30727SAFX_IDD_EDITLINKS30728TAFX_IDD_FILEBROWSE30729UAFX_IDD_BUSY30730VAFX_IDD_OBJECTPROPERTIES30732XAFX_IDD_CHANGESOURCE30733YAFX_IDC_CONTEXTHELP30977]AFX_IDC_MAGNIFY30978^AFX_IDC_SMALLARROWS30979_AFX_IDC_HSPLITBAR30980`AFX_IDC_VSPLITBAR30981aAFX_IDC_NODROPCRSR30982bAFX_IDC_TRACKNWSE30983cAFX_IDC_TRACKNESW30984dAFX_IDC_TRACKNS30985eAFX_IDC_TRACKWE30986fAFX_IDC_TRACK4WAY30987gAFX_IDC_MOVE4WAY30988hAFX_IDC_MOUSE_PAN_NW30998lAFX_IDC_MOUSE_PAN_N30999mAFX_IDC_MOUSE_PAN_NE31000nAFX_IDC_MOUSE_PAN_W31001oAFX_IDC_MOUSE_PAN_HV31002pAFX_IDC_MOUSE_PAN_E31003qAFX_IDC_MOUSE_PAN_SW31004rAFX_IDC_MOUSE_PAN_S31005sAFX_IDC_MOUSE_PAN_SE31006tAFX_IDC_MOUSE_PAN_HORZ31007uAFX_IDC_MOUSE_PAN_VERT31008vAFX_IDC_MOUSE_ORG_HORZ31009yAFX_IDC_MOUSE_ORG_VERT31010zAFX_IDC_MOUSE_ORG_HV31011{AFX_IDC_MOUSE_MASK31012|AFX_IDB_MINIFRAME_MENU30994AFX_IDB_CHECKLISTBOX_9530996AFX_IDR_PREVIEW_ACCEL30997AFX_IDI_STD_MDIFRAME31233AFX_IDI_STD_FRAME31234AFX_IDC_FONTPROP1000AFX_IDC_FONTNAMES1001AFX_IDC_FONTSTYLES1002AFX_IDC_FONTSIZES1003AFX_IDC_STRIKEOUT1004AFX_IDC_UNDERLINE1005AFX_IDC_SAMPLEBOX1006AFX_IDC_COLOR_BLACK1100AFX_IDC_COLOR_WHITE1101AFX_IDC_COLOR_RED1102AFX_IDC_COLOR_GREEN1103AFX_IDC_COLOR_BLUE1104AFX_IDC_COLOR_YELLOW1105AFX_IDC_COLOR_MAGENTA1106AFX_IDC_COLOR_CYAN1107AFX_IDC_COLOR_GRAY1108AFX_IDC_COLOR_LIGHTGRAY1109AFX_IDC_COLOR_DARKRED1110AFX_IDC_COLOR_DARKGREEN1111AFX_IDC_COLOR_DARKBLUE1112AFX_IDC_COLOR_LIGHTBROWN1113AFX_IDC_COLOR_DARKMAGENTA1114AFX_IDC_COLOR_DARKCYAN1115AFX_IDC_COLORPROP1116AFX_IDC_SYSTEMCOLORS1117AFX_IDC_PROPNAME1201AFX_IDC_PICTURE1202AFX_IDC_BROWSE1203AFX_IDC_CLEAR1204AFX_IDD_PROPPAGE_COLOR32257AFX_IDD_PROPPAGE_FONT32258AFX_IDD_PROPPAGE_PICTURE32259AFX_IDB_TRUETYPE32384AFX_IDS_PROPPAGE_UNKNOWN0xFE01AFX_IDS_COLOR_DESKTOP0xFE04AFX_IDS_COLOR_APPWORKSPACE0xFE05AFX_IDS_COLOR_WNDBACKGND0xFE06AFX_IDS_COLOR_WNDTEXT0xFE07AFX_IDS_COLOR_MENUBAR0xFE08AFX_IDS_COLOR_MENUTEXT0xFE09AFX_IDS_COLOR_ACTIVEBAR0xFE0AAFX_IDS_COLOR_INACTIVEBAR0xFE0BAFX_IDS_COLOR_ACTIVETEXT0xFE0CAFX_IDS_COLOR_INACTIVETEXT0xFE0DAFX_IDS_COLOR_ACTIVEBORDER0xFE0EAFX_IDS_COLOR_INACTIVEBORDER0xFE0FAFX_IDS_COLOR_WNDFRAME0xFE10AFX_IDS_COLOR_SCROLLBARS0xFE11AFX_IDS_COLOR_BTNFACE0xFE12AFX_IDS_COLOR_BTNSHADOW0xFE13AFX_IDS_COLOR_BTNTEXT0xFE14AFX_IDS_COLOR_BTNHIGHLIGHT0xFE15AFX_IDS_COLOR_DISABLEDTEXT0xFE16AFX_IDS_COLOR_HIGHLIGHT0xFE17AFX_IDS_COLOR_HIGHLIGHTTEXT0xFE18AFX_IDS_REGULAR0xFE19AFX_IDS_BOLD0xFE1AAFX_IDS_ITALIC0xFE1BAFX_IDS_BOLDITALIC0xFE1CAFX_IDS_SAMPLETEXT0xFE1DAFX_IDS_DISPLAYSTRING_FONT0xFE1EAFX_IDS_DISPLAYSTRING_COLOR0xFE1FAFX_IDS_DISPLAYSTRING_PICTURE0xFE20AFX_IDS_PICTUREFILTER0xFE21AFX_IDS_PICTYPE_UNKNOWN0xFE22AFX_IDS_PICTYPE_NONE0xFE23AFX_IDS_PICTYPE_BITMAP0xFE24AFX_IDS_PICTYPE_METAFILE0xFE25AFX_IDS_PICTYPE_ICON0xFE26AFX_IDS_COLOR_PPG0xFE28AFX_IDS_COLOR_PPG_CAPTION0xFE29AFX_IDS_FONT_PPG0xFE2AAFX_IDS_FONT_PPG_CAPTION0xFE2BAFX_IDS_PICTURE_PPG0xFE2CAFX_IDS_PICTURE_PPG_CAPTION0xFE2DAFX_IDS_PICTUREBROWSETITLE0xFE30AFX_IDS_BORDERSTYLE_00xFE31AFX_IDS_BORDERSTYLE_10xFE32AFX_IDS_VERB_EDIT0xFE40AFX_IDS_VERB_PROPERTIES0xFE41AFX_IDP_PICTURECANTOPEN0xFE83AFX_IDP_PICTURECANTLOAD0xFE84AFX_IDP_PICTURETOOLARGE0xFE85AFX_IDP_PICTUREREADFAILED0xFE86AFX_IDP_E_ILLEGALFUNCTIONCALL0xFEA0AFX_IDP_E_OVERFLOW0xFEA1AFX_IDP_E_OUTOFMEMORY0xFEA2AFX_IDP_E_DIVISIONBYZERO0xFEA3AFX_IDP_E_OUTOFSTRINGSPACE0xFEA4AFX_IDP_E_OUTOFSTACKSPACE0xFEA5AFX_IDP_E_BADFILENAMEORNUMBER0xFEA6AFX_IDP_E_FILENOTFOUND0xFEA7AFX_IDP_E_BADFILEMODE0xFEA8AFX_IDP_E_FILEALREADYOPEN0xFEA9AFX_IDP_E_DEVICEIOERROR0xFEAAAFX_IDP_E_FILEALREADYEXISTS0xFEABAFX_IDP_E_BADRECORDLENGTH0xFEACAFX_IDP_E_DISKFULL0xFEADAFX_IDP_E_BADRECORDNUMBER0xFEAEAFX_IDP_E_BADFILENAME0xFEAFAFX_IDP_E_TOOMANYFILES0xFEB0AFX_IDP_E_DEVICEUNAVAILABLE0xFEB1 AFX_IDP_E_PERMISSIONDENIED0xFEB2 AFX_IDP_E_DISKNOTREADY0xFEB3 AFX_IDP_E_PATHFILEACCESSERROR0xFEB4 AFX_IDP_E_PATHNOTFOUND0xFEB5 AFX_IDP_E_INVALIDPATTERNSTRING0xFEB6AFX_IDP_E_INVALIDUSEOFNULL0xFEB7AFX_IDP_E_INVALIDFILEFORMAT0xFEB8AFX_IDP_E_INVALIDPROPERTYVALUE0xFEB9AFX_IDP_E_INVALIDPROPERTYARRAYINDEX0xFEBAAFX_IDP_E_SETNOTSUPPORTEDATRUNTIME0xFEBBAFX_IDP_E_SETNOTSUPPORTED0xFEBCAFX_IDP_E_NEEDPROPERTYARRAYINDEX0xFEBDAFX_IDP_E_SETNOTPERMITTED0xFEBEAFX_IDP_E_GETNOTSUPPORTEDATRUNTIME0xFEBFAFX_IDP_E_GETNOTSUPPORTED0xFEC0AFX_IDP_E_PROPERTYNOTFOUND0xFEC1AFX_IDP_E_INVALIDCLIPBOARDFORMAT0xFEC2AFX_IDP_E_INVALIDPICTURE0xFEC3AFX_IDP_E_PRINTERERROR0xFEC4AFX_IDP_E_CANTSAVEFILETOTEMP0xFEC5AFX_IDP_E_SEARCHTEXTNOTFOUND0xFEC6AFX_IDP_E_REPLACEMENTSTOOLONG0xFEC7!!($HWB0 res\WinGUI.ico$HWB0 TEXTINCLUDE1$TEXTINCLUDE2$TEXTINCLUDE3$14128IDR_MAINFRAMEC:\stxxl\test\WinGUI\WinGUI.rc;$5100IDD_ABOUTBOXC:\stxxl\test\WinGUI\WinGUI.rcGIDC_STATICIDC_STATICIDC_STATICIDOK$5102IDD_WINGUI_DIALOGC:\stxxl\test\WinGUI\WinGUI.rcRIDOKIDCANCELIDC_STATIC$161VS_VERSION_INFOC:\stxxl\test\WinGUI\WinGUI.rcd$DESIGNINFOGUIDELINES$67IDS_ABOUTBOXe$$$HWB/0C:\stxxl\test\WinGUI\resource.hC:\Programme\Microsoft Visual Studio .NET 2003\Vc7\atlmfc\include/afxres.hC:\Programme\Microsoft Visual Studio .NET 2003\Vc7\atlmfc\include/winres.h$HWB-0TEXTINCLUDE1TEXTINCLUDE2TEXTINCLUDE314128IDR_MAINFRAME5100IDD_ABOUTBOX5102IDD_WINGUI_DIALOG5129IDD_WORKDIALOG161VS_VERSION_INFODESIGNINFOGUIDELINESDESIGNINFOGUIDELINES67G>$HWB.0ID_SEPARATOR0IDOK1VS_VERSION_INFO1IDCANCEL2IDABORT3IDRETRY4IDIGNORE5IDYES6IDNO7IDCLOSE8IDHELP9IDM_ABOUTBOX0x0010IDD_ABOUTBOX100AFX_IDC_LISTBOX100IDS_ABOUTBOX101 AFX_IDC_CHANGE101_APS_NEXT_SYMED_VALUE101IDD_WINGUI_DIALOG102AFX_IDC_BROWSER102IDR_MAINFRAME128IDD_WORKDIALOG129_APS_NEXT_RESOURCE_VALUE130AFX_IDC_PRINT_DOCNAME201AFX_IDC_PRINT_PRINTERNAME202AFX_IDC_PRINT_PORTNAME203AFX_IDC_PRINT_PAGENUM204AFX_IDC_FONTPROP1000IDC_FILLRANDOMBUTTON1000AFX_IDC_FONTNAMES1001IDC_FILENAMEEDIT1001AFX_IDC_FONTSTYLES1002IDC_FILENAMEBUTTON1002AFX_IDC_FONTSIZES1003IDC_INTEGERKEYEDIT1003AFX_IDC_STRIKEOUT1004IDC_FILLVALUEBUTTON1004AFX_IDC_UNDERLINE1005IDC_FORMAT1RADIO1005AFX_IDC_SAMPLEBOX1006IDC_FORMAT2RADIO1006IDC_FILESIZEEDIT1007IDC_FILESIZEEDITMB1008IDC_SORTASCBUTTON1009IDC_MESSAGE11009IDC_SORTDESCBUTTON41010_APS_NEXT_CONTROL_VALUE1010IDC_CHECKASCBUTTON1011IDC_CHECKDESCBUTTON1012IDC_REMDUPLBUTTON1013IDC_CHECKDUPLBUTTON1014IDC_MEMUSAGEEDIT1015AFX_IDC_COLOR_BLACK1100AFX_IDC_COLOR_WHITE1101AFX_IDC_COLOR_RED1102AFX_IDC_COLOR_GREEN1103AFX_IDC_COLOR_BLUE1104AFX_IDC_COLOR_YELLOW1105AFX_IDC_COLOR_MAGENTA1106AFX_IDC_COLOR_CYAN1107AFX_IDC_COLOR_GRAY1108AFX_IDC_COLOR_LIGHTGRAY1109AFX_IDC_COLOR_DARKRED1110AFX_IDC_COLOR_DARKGREEN1111AFX_IDC_COLOR_DARKBLUE1112AFX_IDC_COLOR_LIGHTBROWN1113AFX_IDC_COLOR_DARKMAGENTA1114AFX_IDC_COLOR_DARKCYAN1115AFX_IDC_COLORPROP1116AFX_IDC_SYSTEMCOLORS1117AFX_IDC_PROPNAME1201AFX_IDC_PICTURE1202AFX_IDC_BROWSE1203AFX_IDC_CLEAR1204AFX_IDC_TAB_CONTROL0x3020ID_APPLY_NOW0x3021ID_WIZBACK0x3023ID_WIZNEXT0x3024ID_WIZFINISH0x3025AFX_IDD_NEWTYPEDLG30721AFX_IDD_PRINTDLG30722AFX_IDD_PREVIEW_TOOLBAR30723AFX_IDD_INSERTOBJECT30724AFX_IDD_CHANGEICON30725AFX_IDD_CONVERT30726AFX_IDD_PASTESPECIAL30727AFX_IDD_EDITLINKS30728AFX_IDD_FILEBROWSE30729AFX_IDD_BUSY30730AFX_IDD_OBJECTPROPERTIES30732AFX_IDD_CHANGESOURCE30733AFX_IDC_CONTEXTHELP30977AFX_IDC_MAGNIFY30978AFX_IDC_SMALLARROWS30979AFX_IDC_HSPLITBAR30980AFX_IDC_VSPLITBAR30981AFX_IDC_NODROPCRSR30982AFX_IDC_TRACKNWSE30983AFX_IDC_TRACKNESW30984AFX_IDC_TRACKNS30985AFX_IDC_TRACKWE30986AFX_IDC_TRACK4WAY30987AFX_IDC_MOVE4WAY30988AFX_IDB_MINIFRAME_MENU30994AFX_IDB_CHECKLISTBOX_9530996AFX_IDR_PREVIEW_ACCEL30997AFX_IDC_MOUSE_PAN_NW30998AFX_IDC_MOUSE_PAN_N30999AFX_IDC_MOUSE_PAN_NE31000AFX_IDC_MOUSE_PAN_W31001AFX_IDC_MOUSE_PAN_HV31002AFX_IDC_MOUSE_PAN_E31003AFX_IDC_MOUSE_PAN_SW31004AFX_IDC_MOUSE_PAN_S31005AFX_IDC_MOUSE_PAN_SE31006AFX_IDC_MOUSE_PAN_HORZ31007AFX_IDC_MOUSE_PAN_VERT31008AFX_IDC_MOUSE_ORG_HORZ31009AFX_IDC_MOUSE_ORG_VERT31010AFX_IDC_MOUSE_ORG_HV31011AFX_IDC_MOUSE_MASK31012AFX_IDI_STD_MDIFRAME31233AFX_IDI_STD_FRAME31234AFX_IDD_PROPPAGE_COLOR32257AFX_IDD_PROPPAGE_FONT32258AFX_IDD_PROPPAGE_PICTURE32259AFX_IDB_TRUETYPE32384_APS_NEXT_COMMAND_VALUE32771AFX_IDS_APP_TITLE0xE000AFX_IDS_IDLEMESSAGE0xE001AFX_IDS_HELPMODEMESSAGE0xE002AFX_IDS_APP_TITLE_EMBEDDING0xE003AFX_IDS_COMPANY_NAME0xE004AFX_IDS_OBJ_TITLE_INPLACE0xE005ID_FILE_NEW0xE100ID_FILE_OPEN0xE101ID_FILE_CLOSE0xE102ID_FILE_SAVE0xE103ID_FILE_SAVE_AS0xE104ID_FILE_PAGE_SETUP0xE105ID_FILE_PRINT_SETUP0xE106ID_FILE_PRINT0xE107ID_FILE_PRINT_DIRECT0xE108ID_FILE_PRINT_PREVIEW0xE109ID_FILE_UPDATE0xE10AID_FILE_SAVE_COPY_AS0xE10BID_FILE_SEND_MAIL0xE10CID_FILE_NEW_FRAME0xE10DID_FILE_MRU_FIRST0xE110ID_FILE_MRU_FILE10xE110ID_FILE_MRU_FILE20xE111ID_FILE_MRU_FILE30xE112ID_FILE_MRU_FILE40xE113ID_FILE_MRU_FILE50xE114ID_FILE_MRU_FILE60xE115ID_FILE_MRU_FILE70xE116ID_FILE_MRU_FILE80xE117ID_FILE_MRU_FILE90xE118ID_FILE_MRU_FILE100xE119ID_FILE_MRU_FILE110xE11AID_FILE_MRU_FILE120xE11BID_FILE_MRU_FILE130xE11CID_FILE_MRU_FILE140xE11DID_FILE_MRU_FILE150xE11EID_FILE_MRU_FILE160xE11FID_FILE_MRU_LAST0xE11FID_EDIT_CLEAR0xE120ID_EDIT_CLEAR_ALL0xE121ID_EDIT_COPY0xE122ID_EDIT_CUT0xE123ID_EDIT_FIND0xE124ID_EDIT_PASTE0xE125ID_EDIT_PASTE_LINK0xE126ID_EDIT_PASTE_SPECIAL0xE127ID_EDIT_REPEAT0xE128ID_EDIT_REPLACE0xE129ID_EDIT_SELECT_ALL0xE12AID_EDIT_UNDO0xE12BID_EDIT_REDO0xE12CID_WINDOW_NEW0xE130ID_WINDOW_ARRANGE0xE131ID_WINDOW_CASCADE0xE132ID_WINDOW_TILE_HORZ0xE133ID_WINDOW_TILE_VERT0xE134ID_WINDOW_SPLIT0xE135ID_APP_ABOUT0xE140ID_APP_EXIT0xE141ID_HELP_INDEX0xE142ID_HELP_FINDER0xE143ID_HELP_USING0xE144ID_CONTEXT_HELP0xE145ID_HELP0xE146ID_DEFAULT_HELP0xE147ID_NEXT_PANE0xE150ID_PREV_PANE0xE151ID_FORMAT_FONT0xE160ID_OLE_INSERT_NEW0xE200ID_OLE_EDIT_LINKS0xE201ID_OLE_EDIT_CONVERT0xE202ID_OLE_EDIT_CHANGE_ICON0xE203ID_OLE_EDIT_PROPERTIES0xE204ID_OLE_VERB_FIRST0xE210AFX_ID_PREVIEW_CLOSE0xE300AFX_ID_PREVIEW_NUMPAGE0xE301AFX_ID_PREVIEW_NEXT0xE302AFX_ID_PREVIEW_PREV0xE303AFX_ID_PREVIEW_PRINT0xE304AFX_ID_PREVIEW_ZOOMIN0xE305AFX_ID_PREVIEW_ZOOMOUT0xE306ID_INDICATOR_EXT0xE700ID_INDICATOR_CAPS0xE701ID_INDICATOR_NUM0xE702ID_INDICATOR_SCRL0xE703ID_INDICATOR_OVR0xE704ID_INDICATOR_REC0xE705ID_INDICATOR_KANA0xE706ID_VIEW_TOOLBAR0xE800ID_VIEW_STATUS_BAR0xE801ID_VIEW_REBAR0xE804ID_VIEW_AUTOARRANGE0xE805ID_VIEW_SMALLICON0xE810ID_VIEW_LARGEICON0xE811ID_VIEW_LIST0xE812ID_VIEW_DETAILS0xE813ID_VIEW_LINEUP0xE814ID_VIEW_BYNAME0xE815ID_RECORD_FIRST0xE900ID_RECORD_LAST0xE901ID_RECORD_NEXT0xE902ID_RECORD_PREV0xE903AFX_IDS_SCSIZE0xEF00AFX_IDS_SCMOVE0xEF01AFX_IDS_SCMINIMIZE0xEF02AFX_IDS_SCMAXIMIZE0xEF03AFX_IDS_SCNEXTWINDOW0xEF04AFX_IDS_SCPREVWINDOW0xEF05AFX_IDS_SCCLOSE0xEF06AFX_IDS_SCRESTORE0xEF12AFX_IDS_SCTASKLIST0xEF13AFX_IDS_MDICHILD0xEF1FAFX_IDS_DESKACCESSORY0xEFDAAFX_IDS_OPENFILE0xF000AFX_IDS_SAVEFILE0xF001AFX_IDS_ALLFILTER0xF002AFX_IDS_UNTITLED0xF003AFX_IDS_SAVEFILECOPY0xF004AFX_IDS_PREVIEW_CLOSE0xF005AFX_IDS_UNNAMED_FILE0xF006AFX_IDS_HIDE0xF011AFX_IDP_NO_ERROR_AVAILABLE0xF020AFX_IDS_NOT_SUPPORTED_EXCEPTION0xF021AFX_IDS_RESOURCE_EXCEPTION0xF022AFX_IDS_MEMORY_EXCEPTION0xF023AFX_IDS_USER_EXCEPTION0xF024AFX_IDS_INVALID_ARG_EXCEPTION0xF025AFX_IDS_PRINTONPORT0xF040AFX_IDS_ONEPAGE0xF041AFX_IDS_TWOPAGE0xF042AFX_IDS_PRINTPAGENUM0xF043AFX_IDS_PREVIEWPAGEDESC0xF044AFX_IDS_PRINTDEFAULTEXT0xF045AFX_IDS_PRINTDEFAULT0xF046AFX_IDS_PRINTFILTER0xF047AFX_IDS_PRINTCAPTION0xF048AFX_IDS_PRINTTOFILE0xF049AFX_IDS_OBJECT_MENUITEM0xF080AFX_IDS_EDIT_VERB0xF081AFX_IDS_ACTIVATE_VERB0xF082AFX_IDS_CHANGE_LINK0xF083AFX_IDS_AUTO0xF084AFX_IDS_MANUAL0xF085AFX_IDS_FROZEN0xF086AFX_IDS_ALL_FILES0xF087AFX_IDS_SAVE_MENU0xF088AFX_IDS_UPDATE_MENU0xF089AFX_IDS_SAVE_AS_MENU0xF08AAFX_IDS_SAVE_COPY_AS_MENU0xF08BAFX_IDS_EXIT_MENU0xF08CAFX_IDS_UPDATING_ITEMS0xF08DAFX_IDS_METAFILE_FORMAT0xF08EAFX_IDS_DIB_FORMAT0xF08FAFX_IDS_BITMAP_FORMAT0xF090AFX_IDS_LINKSOURCE_FORMAT0xF091AFX_IDS_EMBED_FORMAT0xF092AFX_IDS_PASTELINKEDTYPE0xF094AFX_IDS_UNKNOWNTYPE0xF095AFX_IDS_RTF_FORMAT0xF096AFX_IDS_TEXT_FORMAT0xF097AFX_IDS_INVALID_CURRENCY0xF098AFX_IDS_INVALID_DATETIME0xF099AFX_IDS_INVALID_DATETIMESPAN0xF09AAFX_IDP_INVALID_FILENAME0xF100AFX_IDP_FAILED_TO_OPEN_DOC0xF101AFX_IDP_FAILED_TO_SAVE_DOC0xF102AFX_IDP_ASK_TO_SAVE0xF103AFX_IDP_FAILED_TO_CREATE_DOC0xF104AFX_IDP_FILE_TOO_LARGE0xF105AFX_IDP_FAILED_TO_START_PRINT0xF106AFX_IDP_FAILED_TO_LAUNCH_HELP0xF107AFX_IDP_INTERNAL_FAILURE0xF108AFX_IDP_COMMAND_FAILURE0xF109AFX_IDP_FAILED_MEMORY_ALLOC0xF10AAFX_IDP_UNREG_DONE0xF10BAFX_IDP_UNREG_FAILURE0xF10CAFX_IDP_DLL_LOAD_FAILED0xF10DAFX_IDP_DLL_BAD_VERSION0xF10EAFX_IDP_PARSE_INT0xF110AFX_IDP_PARSE_REAL0xF111AFX_IDP_PARSE_INT_RANGE0xF112AFX_IDP_PARSE_REAL_RANGE0xF113AFX_IDP_PARSE_STRING_SIZE0xF114AFX_IDP_PARSE_RADIO_BUTTON0xF115AFX_IDP_PARSE_BYTE0xF116AFX_IDP_PARSE_UINT0xF117AFX_IDP_PARSE_DATETIME0xF118AFX_IDP_PARSE_CURRENCY0xF119AFX_IDP_PARSE_GUID0xF11AAFX_IDP_PARSE_TIME0xF11BAFX_IDP_PARSE_DATE0xF11CAFX_IDP_FAILED_INVALID_FORMAT0xF120AFX_IDP_FAILED_INVALID_PATH0xF121AFX_IDP_FAILED_DISK_FULL0xF122AFX_IDP_FAILED_ACCESS_READ0xF123AFX_IDP_FAILED_ACCESS_WRITE0xF124AFX_IDP_FAILED_IO_ERROR_READ0xF125AFX_IDP_FAILED_IO_ERROR_WRITE0xF126AFX_IDP_SCRIPT_ERROR0xF130AFX_IDP_SCRIPT_DISPATCH_EXCEPTION0xF131AFX_IDP_STATIC_OBJECT0xF180AFX_IDP_FAILED_TO_CONNECT0xF181AFX_IDP_SERVER_BUSY0xF182AFX_IDP_BAD_VERB0xF183AFX_IDS_NOT_DOCOBJECT0xF184AFX_IDP_FAILED_TO_NOTIFY0xF185AFX_IDP_FAILED_TO_LAUNCH0xF186AFX_IDP_ASK_TO_UPDATE0xF187AFX_IDP_FAILED_TO_UPDATE0xF188AFX_IDP_FAILED_TO_REGISTER0xF189AFX_IDP_FAILED_TO_AUTO_REGISTER0xF18AAFX_IDP_FAILED_TO_CONVERT0xF18BAFX_IDP_GET_NOT_SUPPORTED0xF18CAFX_IDP_SET_NOT_SUPPORTED0xF18DAFX_IDP_ASK_TO_DISCARD0xF18EAFX_IDP_FAILED_TO_CREATE0xF18FAFX_IDP_FAILED_MAPI_LOAD0xF190AFX_IDP_INVALID_MAPI_DLL0xF191AFX_IDP_FAILED_MAPI_SEND0xF192AFX_IDP_FILE_NONE0xF1A0AFX_IDP_FILE_GENERIC0xF1A1AFX_IDP_FILE_NOT_FOUND0xF1A2AFX_IDP_FILE_BAD_PATH0xF1A3AFX_IDP_FILE_TOO_MANY_OPEN0xF1A4AFX_IDP_FILE_ACCESS_DENIED0xF1A5AFX_IDP_FILE_INVALID_FILE0xF1A6AFX_IDP_FILE_REMOVE_CURRENT0xF1A7AFX_IDP_FILE_DIR_FULL0xF1A8AFX_IDP_FILE_BAD_SEEK0xF1A9AFX_IDP_FILE_HARD_IO0xF1AAAFX_IDP_FILE_SHARING0xF1ABAFX_IDP_FILE_LOCKING0xF1ACAFX_IDP_FILE_DISKFULL0xF1ADAFX_IDP_FILE_EOF0xF1AEAFX_IDP_ARCH_NONE0xF1B0AFX_IDP_ARCH_GENERIC0xF1B1AFX_IDP_ARCH_READONLY0xF1B2AFX_IDP_ARCH_ENDOFFILE0xF1B3AFX_IDP_ARCH_WRITEONLY0xF1B4AFX_IDP_ARCH_BADINDEX0xF1B5AFX_IDP_ARCH_BADCLASS0xF1B6AFX_IDP_ARCH_BADSCHEMA0xF1B7AFX_IDS_OCC_SCALEUNITS_PIXELS0xF1C0AFX_IDS_STATUS_FONT0xF230AFX_IDS_TOOLTIP_FONT0xF231AFX_IDS_UNICODE_FONT0xF232AFX_IDS_MINI_FONT0xF233AFX_IDP_SQL_CONNECT_FAIL0xF281AFX_IDP_SQL_RECORDSET_FORWARD_ONLY0xF282AFX_IDP_SQL_EMPTY_COLUMN_LIST0xF283AFX_IDP_SQL_FIELD_SCHEMA_MISMATCH0xF284AFX_IDP_SQL_ILLEGAL_MODE0xF285AFX_IDP_SQL_MULTIPLE_ROWS_AFFECTED0xF286AFX_IDP_SQL_NO_CURRENT_RECORD0xF287AFX_IDP_SQL_NO_ROWS_AFFECTED0xF288AFX_IDP_SQL_RECORDSET_READONLY0xF289AFX_IDP_SQL_SQL_NO_TOTAL0xF28AAFX_IDP_SQL_ODBC_LOAD_FAILED0xF28BAFX_IDP_SQL_DYNASET_NOT_SUPPORTED0xF28CAFX_IDP_SQL_SNAPSHOT_NOT_SUPPORTED0xF28DAFX_IDP_SQL_API_CONFORMANCE0xF28EAFX_IDP_SQL_SQL_CONFORMANCE0xF28FAFX_IDP_SQL_NO_DATA_FOUND0xF290AFX_IDP_SQL_ROW_UPDATE_NOT_SUPPORTED0xF291AFX_IDP_SQL_ODBC_V2_REQUIRED0xF292AFX_IDP_SQL_NO_POSITIONED_UPDATES0xF293AFX_IDP_SQL_LOCK_MODE_NOT_SUPPORTED0xF294AFX_IDP_SQL_DATA_TRUNCATED0xF295AFX_IDP_SQL_ROW_FETCH0xF296AFX_IDP_SQL_INCORRECT_ODBC0xF297AFX_IDP_SQL_UPDATE_DELETE_FAILED0xF298AFX_IDP_SQL_DYNAMIC_CURSOR_NOT_SUPPORTED0xF299AFX_IDP_SQL_FIELD_NOT_FOUND0xF29AAFX_IDP_SQL_BOOKMARKS_NOT_SUPPORTED0xF29BAFX_IDP_SQL_BOOKMARKS_NOT_ENABLED0xF29CAFX_IDS_DELETED0xF29DAFX_IDP_DAO_ENGINE_INITIALIZATION0xF2B0AFX_IDP_DAO_DFX_BIND0xF2B1AFX_IDP_DAO_OBJECT_NOT_OPEN0xF2B2AFX_IDP_DAO_ROWTOOSHORT0xF2B3AFX_IDP_DAO_BADBINDINFO0xF2B4AFX_IDP_DAO_COLUMNUNAVAILABLE0xF2B5AFX_IDS_HTTP_TITLE0xF2D1AFX_IDS_HTTP_NO_TEXT0xF2D2AFX_IDS_HTTP_BAD_REQUEST0xF2D3AFX_IDS_HTTP_AUTH_REQUIRED0xF2D4AFX_IDS_HTTP_FORBIDDEN0xF2D5AFX_IDS_HTTP_NOT_FOUND0xF2D6AFX_IDS_HTTP_SERVER_ERROR0xF2D7AFX_IDS_HTTP_NOT_IMPLEMENTED0xF2D8AFX_IDS_CHECKLISTBOX_UNCHECK0xF2E1AFX_IDS_CHECKLISTBOX_CHECK0xF2E2AFX_IDS_CHECKLISTBOX_MIXED0xF2E3AFX_IDS_PROPPAGE_UNKNOWN0xFE01AFX_IDS_COLOR_DESKTOP0xFE04AFX_IDS_COLOR_APPWORKSPACE0xFE05AFX_IDS_COLOR_WNDBACKGND0xFE06AFX_IDS_COLOR_WNDTEXT0xFE07AFX_IDS_COLOR_MENUBAR0xFE08AFX_IDS_COLOR_MENUTEXT0xFE09AFX_IDS_COLOR_ACTIVEBAR0xFE0AAFX_IDS_COLOR_INACTIVEBAR0xFE0BAFX_IDS_COLOR_ACTIVETEXT0xFE0CAFX_IDS_COLOR_INACTIVETEXT0xFE0DAFX_IDS_COLOR_ACTIVEBORDER0xFE0EAFX_IDS_COLOR_INACTIVEBORDER0xFE0FAFX_IDS_COLOR_WNDFRAME0xFE10AFX_IDS_COLOR_SCROLLBARS0xFE11AFX_IDS_COLOR_BTNFACE0xFE12AFX_IDS_COLOR_BTNSHADOW0xFE13AFX_IDS_COLOR_BTNTEXT0xFE14AFX_IDS_COLOR_BTNHIGHLIGHT0xFE15AFX_IDS_COLOR_DISABLEDTEXT0xFE16AFX_IDS_COLOR_HIGHLIGHT0xFE17AFX_IDS_COLOR_HIGHLIGHTTEXT0xFE18AFX_IDS_REGULAR0xFE19AFX_IDS_BOLD0xFE1AAFX_IDS_ITALIC0xFE1BAFX_IDS_BOLDITALIC0xFE1CAFX_IDS_SAMPLETEXT0xFE1DAFX_IDS_DISPLAYSTRING_FONT0xFE1EAFX_IDS_DISPLAYSTRING_COLOR0xFE1FAFX_IDS_DISPLAYSTRING_PICTURE0xFE20AFX_IDS_PICTUREFILTER0xFE21AFX_IDS_PICTYPE_UNKNOWN0xFE22AFX_IDS_PICTYPE_NONE0xFE23AFX_IDS_PICTYPE_BITMAP0xFE24AFX_IDS_PICTYPE_METAFILE0xFE25AFX_IDS_PICTYPE_ICON0xFE26AFX_IDS_COLOR_PPG0xFE28AFX_IDS_COLOR_PPG_CAPTION0xFE29AFX_IDS_FONT_PPG0xFE2AAFX_IDS_FONT_PPG_CAPTION0xFE2BAFX_IDS_PICTURE_PPG0xFE2CAFX_IDS_PICTURE_PPG_CAPTION0xFE2DAFX_IDS_PICTUREBROWSETITLE0xFE30AFX_IDS_BORDERSTYLE_00xFE31AFX_IDS_BORDERSTYLE_10xFE32AFX_IDS_VERB_EDIT0xFE40AFX_IDS_VERB_PROPERTIES0xFE41AFX_IDP_PICTURECANTOPEN0xFE83AFX_IDP_PICTURECANTLOAD0xFE84AFX_IDP_PICTURETOOLARGE0xFE85AFX_IDP_PICTUREREADFAILED0xFE86AFX_IDP_E_ILLEGALFUNCTIONCALL0xFEA0AFX_IDP_E_OVERFLOW0xFEA1AFX_IDP_E_OUTOFMEMORY0xFEA2AFX_IDP_E_DIVISIONBYZERO0xFEA3AFX_IDP_E_OUTOFSTRINGSPACE0xFEA4AFX_IDP_E_OUTOFSTACKSPACE0xFEA5AFX_IDP_E_BADFILENAMEORNUMBER0xFEA6AFX_IDP_E_FILENOTFOUND0xFEA7AFX_IDP_E_BADFILEMODE0xFEA8AFX_IDP_E_FILEALREADYOPEN0xFEA9AFX_IDP_E_DEVICEIOERROR0xFEAAAFX_IDP_E_FILEALREADYEXISTS0xFEABAFX_IDP_E_BADRECORDLENGTH0xFEACAFX_IDP_E_DISKFULL0xFEADAFX_IDP_E_BADRECORDNUMBER0xFEAEAFX_IDP_E_BADFILENAME0xFEAFAFX_IDP_E_TOOMANYFILES0xFEB0AFX_IDP_E_DEVICEUNAVAILABLE0xFEB1AFX_IDP_E_PERMISSIONDENIED0xFEB2AFX_IDP_E_DISKNOTREADY0xFEB3AFX_IDP_E_PATHFILEACCESSERROR0xFEB4AFX_IDP_E_PATHNOTFOUND0xFEB5AFX_IDP_E_INVALIDPATTERNSTRING0xFEB6AFX_IDP_E_INVALIDUSEOFNULL0xFEB7AFX_IDP_E_INVALIDFILEFORMAT0xFEB8AFX_IDP_E_INVALIDPROPERTYVALUE0xFEB9AFX_IDP_E_INVALIDPROPERTYARRAYINDEX0xFEBAAFX_IDP_E_SETNOTSUPPORTEDATRUNTIME0xFEBBAFX_IDP_E_SETNOTSUPPORTED0xFEBCAFX_IDP_E_NEEDPROPERTYARRAYINDEX0xFEBDAFX_IDP_E_SETNOTPERMITTED0xFEBEAFX_IDP_E_GETNOTSUPPORTEDATRUNTIME0xFEBFAFX_IDP_E_GETNOTSUPPORTED0xFEC0AFX_IDP_E_PROPERTYNOTFOUND0xFEC1AFX_IDP_E_INVALIDCLIPBOARDFORMAT0xFEC2AFX_IDP_E_INVALIDPICTURE0xFEC3AFX_IDP_E_PRINTERERROR0xFEC4AFX_IDP_E_CANTSAVEFILETOTEMP0xFEC5AFX_IDP_E_SEARCHTEXTNOTFOUND0xFEC6AFX_IDP_E_REPLACEMENTSTOOLONG0xFEC7IDC_STATIC-1 4TEXTINCLUDE0resource.h4TEXTINCLUDE0#include "afxres.h" t4TEXTINCLUDE0#define _AFX_NO_SPLITTER_RESOURCES #define _AFX_NO_OLE_RESOURCES #define _AFX_NO_TRACKER_RESOURCES #define _AFX_NO_PROPERTY_RESOURCES #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) LANGUAGE 9, 1 #pragma code_page(1252) #include "res\WinGUI.rc2" // non-Microsoft Visual C++ edited resources #include "afxres.rc" // Standard components #endif h (0`wwwwwwwwwwwwwwwwwwwwww׈wwwwwwwwwwwwwwwwwwwwwwxxx}׈xxx}wwwwwww}}}}}}}}}}}}}}}}}wwwwwwwwwww}׈x}wwwwwwww݀?? ( @wwwwwwwwwwwwww׈wwwwwwwwwwwwwwxx}׈xxx}www}}}}}}}}}wwwwwww}׈x}wwww݀?( ( wwwwwww}x}x}x}x}x}x}x}wwwwwww}ׇw}ׁׁׁ׈wwwwݨ (0`wXkqN]tno0-1-6-˭ymC,B,w:"o\hP]>te=ggrlgNɓbћit5u6ˑXČV۰̯À5ˎI٦nڧo仐Á6dž:ʋ=ȋAغˌ=ݭlܭpޱw彉ղʌ7ΗF{Ҩ~Ȋ'۩]Ϡ޸ڤJ֡بڭ۰ݴ١/͊ώєҖӚ՟ץmz˃N]:IH\OUJI=cY\ULGa]gcqmjernyvnkQOWV|z‰Ďǔȕʚ˝ə̞̟ΤհܾЩִںL]dn“@b~ϧֶ>88+/h\^}qq[`//"QRT$1=>>8+2j\^sccy\`2/"OQ$%=>>*2i\^sccy\a//"NO66**L=>(2i\]~rccy\a//"WNFTHI*++LL=(/h\^|~rccs\`//'VWRFTHJCDKLL)2j\]x|~rccp~\_//'VVQRFTHJCDKL(/i\^wx|~pcccccb\`//'UVOQRFGHJCDK(/i\]wwx|pcckrss\a//0UUNOQRSGHIJD(2i\^vwwxpccr\`///YUWNOQRFTHIJ)/j\]uvwwmccp\`//9YYVWNO5;*THI)2j\]uuvwmccp\a//9XYVVWNSTH)2i\]ouuvmccbbbbbs\a//@XX0RST)/i\]oouulefffggkt\`/2@ZXX:;NPRF(/h\]loouuvwwx|~\_2/@ZZXXYYUUUVWNOPQ(/i\]ffggkkqqqzzz{{{\_//?MMMMEEEAAAA33452i\\\\\\\\\\\\\\\\\\\`//&&&&&--&&&&-&&&&./illlllllll##"      пѻ  пҿ ǿ ĭѻѬĮĮпĮдĭϳγι͹ƹĮ̸˷հ®ŭᨼ켨켼ǻ?? ( @nPhixѶҷ1-ŦvyufbJƝŜO1aAgO`>eDl™d=iIŽpȢַd8hEsrHg͹ˆXOດȧÀ5ĝĄ:ʋ=ݰzԶˌ=ҚSܭn澋ݿΐ;ҘH۩^仁ȗі;qӦٲ۸ݩL߯_ب֩ڭ۰߹٢5͊ѕӚԟj̅ؠL3_s-GCBHBvBuAuBvD7m3eH%0_J.M5>w+I4D2P=F9I=J=TGf[MEaYg^og`Zf_rld`ytzuqqn~ƔŎșʞ̞ʙ̞˞ΥҩٷںܾԱ׿|ʣЭطZ7s8t5uX^d3Zz#$$8?IS\b*>Z~##$WpWo/38<Xe`dlstyTryyhz@sGxv6gDrKvNxU8^j}!9,']ZZZZZZZZZZZWV-1---------1-\gmV2.AHBC5D;<<(-^iz|kV2.P:#!!+=>(-\ecokV239 $=(-]e{cokV73@ GJ'0<(-^e~xcokV78@ OGJKD;*1]d}~wca``kV78F OOGJKD*1\dy}rch{kV7EF MNOGIK/1\buyrcjkV?EE RR.#:I/-[btuncfssvkV?LE&%"9G41]_ptqhhhjjkV?LTE@NO41]_mptuy}~lV6SUTTQQQRRN91[WXXXYXXYXYYWV-)))))))))),,$ ſ ū ˷ʪڪٶ׶ֽսԼϮ󹺺ū¿?h ( uVhtzԷ™T,d<ڼʔrʔsd6c6YŠ`ϛoˆU֡qաp֢qݱҘXҙYԟeӞȅIӜYҙXӚQӛQȈ)Ȍ7ȔݾЖ8ї<Ҙ?Çٲҟצ_s-C<<==.ECK2LPV.$ E@J3MOU.  !D?H31IT.-,%B;G1JKS.( ) *E9A011R.&#++E/4678:."&' NQWhX^XXXe rpqt}~]mv\l{[izZjywYdjklnocsgba`_f|ux||||d}caV7 GJ*1dychV7 OG/1 (0` # # # # # # # #! # #! #! # # # # # # # #gdc # # #! # # # # # # # # # # # # # # # # #BuAuBvBvBvBvAuAuBvBvAuBuBvBvBvBvAuAuBv! #o3t5t5t5t5t5t5t5t5t6t5t5u6t5t5t5t6t5t5t5! #! #aZIIIIHIIHIIIIIHHHIIIBvʋ=ʋ=ˌ=ʋ=ʋ=ʋ=ˋ=ˋ=ʋ=ʋ=ʋ=ʋ=ˋ=ʋ=ʋ=ˌ=ʋ=ʋ=ˌ=ʋ=lR! #aYIHRΗFd7d8d9dHRZ`invyʁˆ΍єҙڦnʋ=lS! #bZH=zB2D4E9F:H?H@KDLHNJQOROUSVUWWYZM^IBuʋ=ˌ=~؟!ؠ*٢6٢;٣CڥKڦPڧWۨZ۪`۪c۬jݭnݮqݰwҙ`ˌ=lR! #bZIIIIIIHHIHIIHHIIIHHAuˌ=ˌ=À5Á5À5À5À5À5€5À5Á5À5Á5À5Á5Á5À5À5dž:ʋ=lR! #~T>jZfWeVaS`Q]OZLZK@b;wi=ua=ua=ua=uanglq,,,,2#4@egdc$s$;kcgm,,,,1$4@egdc%s#:j_cg"=, 9y!:, 91#5@fgdc%t$8iZ_cgmqv{1#5Afgdc$s$0[FHLQSY[_aehjoqum.#5@egdc%s$$$###$#$$$$#$##$##$5@fgdc8w##$$#$#$$$##$##$$##$Xf\{|vkkh\{qvh\{h\{ąxxttqommkkkh?? ( @ # # # # # # # # # # # # # # # # # # # # # # # # # #BL@BM@BM@BL@BL@BL@BL@BM@CMABM@BL@BL@ #w\Rv\Rw]Sw\Rw\Rw\Sv\Rv\Rw\Rw]Sw]Sw]StYQ1-/ #AuHIHHHHHIHHHI_s-ʋ=ˌ=ˋ=ʋ=ʋ=ˌ=ʋ=ˋ=ʋ=ˌ=ˌ=ʋ=t6REE #BuI5|ҭ׵ظܿŷͺPF_s-ӛVݯ}Ԧթٳ۷޿ťt6RDD #AuP=˝ҩʞqnI<_s-ӚTݰyԟɘknrsʬt5REE #BvN8ɘ̞0_OH۾I=^s,ҚQݮp彂aAL.hEiJX7bIεȧt5RDE #BvM6Ŏʙ0`LDڻ۾I=_s-ҙM۫kq1.fHب۰ດÍqԶǤu6RDD #AuK2Ŏ~y0_LDհٸܾI=_s-ҙK۩_l1.fFӜب۰şʋ=REE #BvJ.~yt0_3f6l6mÔܾI=^s,ҙFܪ]b1.dCҗӛةۯߺěˌ=REE #AuI+uq}rj0_E5Υط۾I=_s-їEڦP߯]1-eA͊ҕӜب٭ߺʋ=SEE #BuH'rmuqnf0_G9Ȕ̞ҩԯٷI=_s-ї>٥IެQ0-d=ʃ̇ޱxŠcȘڭʋ=REE #BuG!f_rmf[0_>w+^Wa\c_ȚԮI=^s,җ=٢<ݪHB,T4OˆXrHa?㸀ب彊ʋ=REE #BuFaXg_g]B.D3D4G8G:ΤI=_s-і7١/HMc6d8d;e?vѕӛ澊ˌ=SEE #BvCWHbYf^pkuq}ōǔ̞I<^s,ΐ;ؠ2GV_lt˃ˇє廂ʋ=SEE #AuFBCCCCBCCBCG_s-ʋ=À5À5À5À5€5À5Á5Á5À5À5Ń8„;tcc #Ʋ׿ӶͫɢZ5u7t7s7t7t7t3ZzWoWpWpWpWoTriwlÙȡֶ˼˼`#STWY[^_ccf]$vWjuezƦֶd$$pM\gOzl}r\$6_,U܏,!9$XBecX|tzly$9\;ki,#4@ey#Nx2cd',$?Ruz$yJv,$CXzy#rxGta,,$CXzy$krDr(t!:,#CYzy#clAoJvԇ,,$CXzy$^eAs,Gxۂ,,#BXzz#V`eltyls#CXzz$/034578;<=<$CY{=[WTQMHE?=86+s}}_˘}_˘࠸؛؛؛؛؛؛ؘ?h  ( GI=J=I=I=I=_s-̏IҘXҘXҙYҘXҙY|Xfdcd`ѩ;w _s-ԞdȔd7d6ޫZgec]U˜;w ۽и_s-ӜYc6Zݰʔr˫ZfdcXO;w _s-LJ)і9җ<ԛQӜYӞe\փԹv,i;z;z;z;zP2ChooseP\Fill with random integer keysAFP>Fill with integer keyE_PgVfP2Go!PKSort in ascending orderFOP2#File formatTR P@+e 4-bytes key, 12-bytes info P@:e 4-bytes key, 28-bytes infoPmFile sizeOB Phj;Pmx 4KB =_CPLSortfP2Go!ETPOSort in descending orderfP2Go!WPJCheck ascending orderSEPNCheck descending orderfP2Go!FIfP2Go!P/ScanPZScan and remove duplicatesfP 2Go!E1P`Scan and check for duplicatesfX2Go!MRPKLInternal memory to use PgISPLMBytes(Pj*PlMBytes 0*DialogMS Shell DlgPWorking ...0 0 04VS_VERSION_INFO?StringFileInfol040904e4JCompanyNameTODO: <Company name>ZFileDescriptionTODO: <File description>0FileVersion1.0.0.16 InternalNameWinGUI.exe0LegalCopyrightTODO: (c) <Company name>. All rights reserved.> OriginalFilenameWinGUI.exeJProductNameTODO: <Product name>4ProductVersion1.0.0.1DVarFileInfo$Translation DDESIGNINFOGUIDELINES0 d ,0f \0EG0EG KHDDESIGNINFOGUIDELINES00EG#@ 0 &About WinGUI...$HWB#DHWB@HWB0 (@HWB0 AHWB0 (CHWB/0DHWB-0G>DHWB.0 pTEXTINCLUDE0TEXTINCLUDE0tTEXTINCLUDE0h( h0h Hh 0H<d0 f0 00h0 DESIGNINFOGUIDELINES0 HDESIGNINFOGUIDELINES0@0 stxxl-1.3.1/test/WinGUI/Debug/0000755000175000017500000000000011536252420015621 5ustar andreasandreasstxxl-1.3.1/test/WinGUI/WorkDialog.h0000644000175000017500000000146110631532342017007 0ustar andreasandreas#pragma once #define WM_WORK_THREAD_FINISHED (WM_USER + 0x101) #define WORK_TIMER_ID (1) // CWorkDialog dialog class CWorkDialog : public CDialog { DECLARE_DYNAMIC(CWorkDialog) public: CWorkDialog(CWnd * pParent = NULL); // standard constructor virtual ~CWorkDialog(); // Dialog Data enum { IDD = IDD_WORKDIALOG }; protected: virtual void DoDataExchange(CDataExchange * pDX); // DDX/DDV support DECLARE_MESSAGE_MAP() public: afx_msg void OnBnClickedOk(); afx_msg void OnBnClickedCancel(); CString m_Message; protected: CWinThread * thread; public: afx_msg LRESULT OnThreadFinished(WPARAM wparam, LPARAM lparam); void SetThread(CWinThread * thread_); afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); afx_msg void OnTimer(UINT nIDEvent); }; stxxl-1.3.1/test/WinGUI/WinGUI.h0000644000175000017500000000075210631532342016051 0ustar andreasandreas// WinGUI.h : main header file for the PROJECT_NAME application // #pragma once #ifndef __AFXWIN_H__ #error include 'stdafx.h' before including this file for PCH #endif #include "resource.h" // main symbols // CWinGUIApp: // See WinGUI.cpp for the implementation of this class // class CWinGUIApp : public CWinApp { public: CWinGUIApp(); // Overrides public: virtual BOOL InitInstance(); // Implementation DECLARE_MESSAGE_MAP() }; extern CWinGUIApp theApp;stxxl-1.3.1/test/WinGUI/res/0000755000175000017500000000000011536252421015365 5ustar andreasandreasstxxl-1.3.1/test/WinGUI/res/WinGUI.manifest0000644000175000017500000000124210622615152020215 0ustar andreasandreas Your app description here stxxl-1.3.1/test/WinGUI/res/WinGUI.rc20000644000175000017500000000060010622615152017072 0ustar andreasandreas// // WinGUI.RC2 - resources Microsoft Visual C++ does not edit directly // #ifdef APSTUDIO_INVOKED #error this file is not editable by Microsoft Visual C++ #endif //APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// // Add manually edited resources here... ///////////////////////////////////////////////////////////////////////////// stxxl-1.3.1/test/WinGUI/res/WinGUI.ico0000644000175000017500000005217610275653004017177 0ustar andreasandreas 00h ( 00 h^"00'  nDhQ(0`wwwwwwwwwwwwwwwwwwwwww׈wwwwwwwwwwwwwwwwwwwwwwxxx}׈xxx}wwwwwww}}}}}}}}}}}}}}}}}wwwwwwwwwww}׈x}wwwwwwww݀??( @wwwwwwwwwwwwww׈wwwwwwwwwwwwwwxx}׈xxx}www}}}}}}}}}wwwwwww}׈x}wwww݀?( wwwwwww}x}x}x}x}x}x}x}wwwwwww}ׇw}ׁׁׁ׈wwww(0`wXkqN]tno0-1-6-˭ymC,B,w:"o\hP]>te=ggrlgNɓbћit5u6ˑXČV۰̯À5ˎI٦nڧo仐Á6dž:ʋ=ȋAغˌ=ݭlܭpޱw彉ղʌ7ΗF{Ҩ~Ȋ'۩]Ϡ޸ڤJ֡بڭ۰ݴ١/͊ώєҖӚ՟ץmz˃N]:IH\OUJI=cY\ULGa]gcqmjernyvnkQOWV|z‰Ďǔȕʚ˝ə̞̟ΤհܾЩִںL]dn“@b~ϧֶ>88+/h\^}qq[`//"QRT$1=>>8+2j\^sccy\`2/"OQ$%=>>*2i\^sccy\a//"NO66**L=>(2i\]~rccy\a//"WNFTHI*++LL=(/h\^|~rccs\`//'VWRFTHJCDKLL)2j\]x|~rccp~\_//'VVQRFTHJCDKL(/i\^wx|~pcccccb\`//'UVOQRFGHJCDK(/i\]wwx|pcckrss\a//0UUNOQRSGHIJD(2i\^vwwxpccr\`///YUWNOQRFTHIJ)/j\]uvwwmccp\`//9YYVWNO5;*THI)2j\]uuvwmccp\a//9XYVVWNSTH)2i\]ouuvmccbbbbbs\a//@XX0RST)/i\]oouulefffggkt\`/2@ZXX:;NPRF(/h\]loouuvwwx|~\_2/@ZZXXYYUUUVWNOPQ(/i\]ffggkkqqqzzz{{{\_//?MMMMEEEAAAA33452i\\\\\\\\\\\\\\\\\\\`//&&&&&--&&&&-&&&&./illlllllll##"      пѻ  пҿ ǿ ĭѻѬĮĮпĮдĭϳγι͹ƹĮ̸˷հ®ŭᨼ켨켼ǻ??( @nPhixѶҷ1-ŦvyufbJƝŜO1aAgO`>eDl™d=iIŽpȢַd8hEsrHg͹ˆXOດȧÀ5ĝĄ:ʋ=ݰzԶˌ=ҚSܭn澋ݿΐ;ҘH۩^仁ȗі;qӦٲ۸ݩL߯_ب֩ڭ۰߹٢5͊ѕӚԟj̅ؠL3_s-GCBHBvBuAuBvD7m3eH%0_J.M5>w+I4D2P=F9I=J=TGf[MEaYg^og`Zf_rld`ytzuqqn~ƔŎșʞ̞ʙ̞˞ΥҩٷںܾԱ׿|ʣЭطZ7s8t5uX^d3Zz#$$8?IS\b*>Z~##$WpWo/38<Xe`dlstyTryyhz@sGxv6gDrKvNxU8^j}!9,']ZZZZZZZZZZZWV-1---------1-\gmV2.AHBC5D;<<(-^iz|kV2.P:#!!+=>(-\ecokV239 $=(-]e{cokV73@ GJ'0<(-^e~xcokV78@ OGJKD;*1]d}~wca``kV78F OOGJKD*1\dy}rch{kV7EF MNOGIK/1\buyrcjkV?EE RR.#:I/-[btuncfssvkV?LE&%"9G41]_ptqhhhjjkV?LTE@NO41]_mptuy}~lV6SUTTQQQRRN91[WXXXYXXYXYYWV-)))))))))),,$ ſ ū ˷ʪڪٶ׶ֽսԼϮ󹺺ū¿?( uVhtzԷ™T,d<ڼʔrʔsd6c6YŠ`ϛoˆU֡qաp֢qݱҘXҙYԟeӞȅIӜYҙXӚQӛQȈ)Ȍ7ȔݾЖ8ї<Ҙ?Çٲҟצ_s-C<<==.ECK2LPV.$ E@J3MOU.  !D?H31IT.-,%B;G1JKS.( ) *E9A011R.&#++E/4678:."&' NQWhX^XXXe rpqt}~]mv\l{[izZjywYdjklnocsgba`_f|ux||||d}caV7 GJ*1dychV7 OG/1(0` # # # # # # # #! # #! #! # # # # # # # #gdc # # #! # # # # # # # # # # # # # # # # #BuAuBvBvBvBvAuAuBvBvAuBuBvBvBvBvAuAuBv! #o3t5t5t5t5t5t5t5t5t6t5t5u6t5t5t5t6t5t5t5! #! #aZIIIIHIIHIIIIIHHHIIIBvʋ=ʋ=ˌ=ʋ=ʋ=ʋ=ˋ=ˋ=ʋ=ʋ=ʋ=ʋ=ˋ=ʋ=ʋ=ˌ=ʋ=ʋ=ˌ=ʋ=lR! #aYIHRΗFd7d8d9dHRZ`invyʁˆ΍єҙڦnʋ=lS! #bZH=zB2D4E9F:H?H@KDLHNJQOROUSVUWWYZM^IBuʋ=ˌ=~؟!ؠ*٢6٢;٣CڥKڦPڧWۨZ۪`۪c۬jݭnݮqݰwҙ`ˌ=lR! #bZIIIIIIHHIHIIHHIIIHHAuˌ=ˌ=À5Á5À5À5À5À5€5À5Á5À5Á5À5Á5Á5À5À5dž:ʋ=lR! #~T>jZfWeVaS`Q]OZLZK@b;wi=ua=ua=ua=uanglq,,,,2#4@egdc$s$;kcgm,,,,1$4@egdc%s#:j_cg"=, 9y!:, 91#5@fgdc%t$8iZ_cgmqv{1#5Afgdc$s$0[FHLQSY[_aehjoqum.#5@egdc%s$$$###$#$$$$#$##$##$5@fgdc8w##$$#$#$$$##$##$$##$Xf\{|vkkh\{qvh\{h\{ąxxttqommkkkh??( @ # # # # # # # # # # # # # # # # # # # # # # # # # #BL@BM@BM@BL@BL@BL@BL@BM@CMABM@BL@BL@ #w\Rv\Rw]Sw\Rw\Rw\Sv\Rv\Rw\Rw]Sw]Sw]StYQ1-/ #AuHIHHHHHIHHHI_s-ʋ=ˌ=ˋ=ʋ=ʋ=ˌ=ʋ=ˋ=ʋ=ˌ=ˌ=ʋ=t6REE #BuI5|ҭ׵ظܿŷͺPF_s-ӛVݯ}Ԧթٳ۷޿ťt6RDD #AuP=˝ҩʞqnI<_s-ӚTݰyԟɘknrsʬt5REE #BvN8ɘ̞0_OH۾I=^s,ҚQݮp彂aAL.hEiJX7bIεȧt5RDE #BvM6Ŏʙ0`LDڻ۾I=_s-ҙM۫kq1.fHب۰ດÍqԶǤu6RDD #AuK2Ŏ~y0_LDհٸܾI=_s-ҙK۩_l1.fFӜب۰şʋ=REE #BvJ.~yt0_3f6l6mÔܾI=^s,ҙFܪ]b1.dCҗӛةۯߺěˌ=REE #AuI+uq}rj0_E5Υط۾I=_s-їEڦP߯]1-eA͊ҕӜب٭ߺʋ=SEE #BuH'rmuqnf0_G9Ȕ̞ҩԯٷI=_s-ї>٥IެQ0-d=ʃ̇ޱxŠcȘڭʋ=REE #BuG!f_rmf[0_>w+^Wa\c_ȚԮI=^s,җ=٢<ݪHB,T4OˆXrHa?㸀ب彊ʋ=REE #BuFaXg_g]B.D3D4G8G:ΤI=_s-і7١/HMc6d8d;e?vѕӛ澊ˌ=SEE #BvCWHbYf^pkuq}ōǔ̞I<^s,ΐ;ؠ2GV_lt˃ˇє廂ʋ=SEE #AuFBCCCCBCCBCG_s-ʋ=À5À5À5À5€5À5Á5Á5À5À5Ń8„;tcc #Ʋ׿ӶͫɢZ5u7t7s7t7t7t3ZzWoWpWpWpWoTriwlÙȡֶ˼˼`#STWY[^_ccf]$vWjuezƦֶd$$pM\gOzl}r\$6_,U܏,!9$XBecX|tzly$9\;ki,#4@ey#Nx2cd',$?Ruz$yJv,$CXzy#rxGta,,$CXzy$krDr(t!:,#CYzy#clAoJvԇ,,$CXzy$^eAs,Gxۂ,,#BXzz#V`eltyls#CXzz$/034578;<=<$CY{=[WTQMHE?=86+s}}_˘}_˘࠸؛؛؛؛؛؛ؘ?( GI=J=I=I=I=_s-̏IҘXҘXҙYҘXҙY|Xfdcd`ѩ;w _s-ԞdȔd7d6ޫZgec]U˜;w ۽и_s-ӜYc6Zݰʔr˫ZfdcXO;w _s-LJ)і9җ<ԛQӜYӞe\փԹv,i;z;z;z;z #include struct type1 { int key; int data[3]; bool operator == (const type1 & a) const { return key == a.key; } type1() { } type1(int key_) : key(key_) { } }; struct type2 { int key; int data[7]; bool operator == (const type2 & a) const { return key == a.key; } type2() { } type2(int key_) : key(key_) { } }; struct my_rnd { stxxl::random_number32 rnd; int operator() () const { return rnd() % 0xfffff; } }; template struct LessCmp { bool operator () (const T & a, const T & b) const { return a.key < b.key; } static int min_value() { return (std::numeric_limits < int > ::min)(); } static int max_value() { return (std::numeric_limits < int > ::max)(); } }; template struct GreaterCmp { bool operator () (const T & a, const T & b) const { return a.key > b.key; } static int min_value() { return (std::numeric_limits < int > ::max)(); } static int max_value() { return (std::numeric_limits < int > ::min)(); } }; #endif // INCLUDE_USER_TYPESstxxl-1.3.1/test/WinGUI/resource.hm0000644000175000017500000000146010622615152016751 0ustar andreasandreas// Microsoft Visual C++ generated Help ID include file. // Used by WinGUI.rc // #define HIDC_CHECKASCBUTTON 0x806603f3 // IDD_WINGUI_DIALOG [English (U.S.)] #define HIDC_CHECKDESCBUTTON 0x806603f4 // IDD_WINGUI_DIALOG [English (U.S.)] #define HIDC_CHECKDUPLBUTTON 0x806603f6 // IDD_WINGUI_DIALOG [English (U.S.)] #define HIDC_FILLRANDOMBUTTON 0x806603e8 // IDD_WINGUI_DIALOG [English (U.S.)] #define HIDC_FILLVALUEBUTTON 0x806603ec // IDD_WINGUI_DIALOG [English (U.S.)] #define HIDC_REMDUPLBUTTON 0x806603f5 // IDD_WINGUI_DIALOG [English (U.S.)] #define HIDC_SORTASCBUTTON 0x806603f1 // IDD_WINGUI_DIALOG [English (U.S.)] #define HIDC_SORTDESCBUTTON4 0x806603f2 // IDD_WINGUI_DIALOG [English (U.S.)] stxxl-1.3.1/test/WinGUI/WinGUI.sln0000644000175000017500000000152511260335444016420 0ustar andreasandreasMicrosoft Visual Studio Solution File, Format Version 10.00 # Visual Studio 2008 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WinGUI", "WinGUI.vcproj", "{D3DE8D18-0A0A-4884-869A-B8C3AF838CF8}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 Release|Win32 = Release|Win32 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {D3DE8D18-0A0A-4884-869A-B8C3AF838CF8}.Debug|Win32.ActiveCfg = Debug|Win32 {D3DE8D18-0A0A-4884-869A-B8C3AF838CF8}.Debug|Win32.Build.0 = Debug|Win32 {D3DE8D18-0A0A-4884-869A-B8C3AF838CF8}.Release|Win32.ActiveCfg = Release|Win32 {D3DE8D18-0A0A-4884-869A-B8C3AF838CF8}.Release|Win32.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection EndGlobal stxxl-1.3.1/test/WinGUI/StxxlWorkThread.cpp0000644000175000017500000001315710631532342020422 0ustar andreasandreas// StxxlWorkThread.cpp : implementation file // #include "stdafx.h" #include "WinGUI.h" #include "StxxlWorkThread.h" #include ".\stxxlworkthread.h" #include "WorkDialog.h" #include "WinGUIDlg.h" #include "UserTypes.h" // CStxxlWorkThread IMPLEMENT_DYNCREATE(CStxxlWorkThread, CWinThread) CStxxlWorkThread::CStxxlWorkThread() { } CStxxlWorkThread::~CStxxlWorkThread() { } BOOL CStxxlWorkThread::InitInstance() { // TODO: perform and per-thread initialization here return TRUE; } int CStxxlWorkThread::ExitInstance() { // TODO: perform any per-thread cleanup here return CWinThread::ExitInstance(); } BEGIN_MESSAGE_MAP(CStxxlWorkThread, CWinThread) END_MESSAGE_MAP() // CStxxlWorkThread message handlers template void CStxxlWorkThread::FillRandom(CString & path, LONGLONG filesize, T dummy) { stxxl::wincall_file myfile(LPCSTR(dlg->m_Filename), stxxl::file::CREAT | stxxl::file::DIRECT | stxxl::file::RDWR); stxxl::int64 vectorsize = dlg->m_Filesize * 4096 / sizeof(T); stxxl::vector myvector(&myfile); myvector.resize(vectorsize); stxxl::generate(myvector.begin(), myvector.end(), my_rnd(), 4); } template void CStxxlWorkThread::FillValue(CString & path, LONGLONG filesize, int value, T dummy) { stxxl::wincall_file myfile(LPCSTR(dlg->m_Filename), stxxl::file::CREAT | stxxl::file::DIRECT | stxxl::file::RDWR); stxxl::int64 vectorsize = dlg->m_Filesize * 4096 / sizeof(T); stxxl::vector myvector(&myfile); myvector.resize(vectorsize); std::fill(myvector.begin(), myvector.end(), value); } template void CStxxlWorkThread::Sort(CString & path, unsigned mem_usage, Cmp cmp, T dummy) { stxxl::wincall_file myfile(LPCSTR(dlg->m_Filename), stxxl::file::CREAT | stxxl::file::DIRECT | stxxl::file::RDWR); stxxl::vector myvector(&myfile); if ((myvector.size() * sizeof(T)) % 4096) { AfxMessageBox("File can not be sorted because it is accessed with direct I/O\n" "and its size is not a multiple of 4KBytes."); return; } stxxl::sort(myvector.begin(), myvector.end(), cmp, mem_usage * 1024 * 1024); } template void CStxxlWorkThread::CheckOrder(CString & path, Cmp cmp, T dummy) { stxxl::wincall_file myfile(LPCSTR(dlg->m_Filename), stxxl::file::CREAT | stxxl::file::DIRECT | stxxl::file::RDWR); stxxl::vector myvector(&myfile); if ((myvector.size() * sizeof(T)) % 4096) { AfxMessageBox("File can not be sorted because it is accessed with direct I/O\n" "and its size is not a multiple of 4KBytes."); return; } bool sorted = stxxl::is_sorted(myvector.begin(), myvector.end(), cmp); if (sorted) AfxMessageBox("The file is sorted"); else AfxMessageBox("The file is NOT sorted"); } template void CStxxlWorkThread::DelDuplicates(CString & path, unsigned mem_usage, T dummy) { stxxl::wincall_file myfile(LPCSTR(dlg->m_Filename), stxxl::file::CREAT | stxxl::file::DIRECT | stxxl::file::RDWR); stxxl::vector myvector(&myfile); if ((myvector.size() * sizeof(T)) % 4096) { AfxMessageBox("File can not be sorted because it is accessed with direct I/O\n" "and its size is not a multiple of 4KBytes."); return; } stxxl::sort(myvector.begin(), myvector.end(), LessCmp(), mem_usage * 1024 * 1024); std::unique(myvector.begin(), myvector.end()); } int CStxxlWorkThread::Run() { // TODO: Add your specialized code here and/or call the base class switch (taskid) { case FILL_RANDOM: if (dlg->m_Format1) FillRandom(dlg->m_Filename, dlg->m_Filesize, type2()); else FillRandom(dlg->m_Filename, dlg->m_Filesize, type1()); break; case FILL_VALUE: if (dlg->m_Format1) FillValue(dlg->m_Filename, dlg->m_Filesize, dlg->m_Key, type2()); else FillValue(dlg->m_Filename, dlg->m_Filesize, dlg->m_Key, type1()); break; case SORT_ASC: if (dlg->m_Format1) Sort(dlg->m_Filename, dlg->m_MemUsage, LessCmp(), type2()); else Sort(dlg->m_Filename, dlg->m_MemUsage, LessCmp(), type1()); break; case SORT_DESC: if (dlg->m_Format1) Sort(dlg->m_Filename, dlg->m_MemUsage, GreaterCmp(), type2()); else Sort(dlg->m_Filename, dlg->m_MemUsage, GreaterCmp(), type1()); break; case CHECK_ASC: if (dlg->m_Format1) CheckOrder(dlg->m_Filename, LessCmp(), type2()); else CheckOrder(dlg->m_Filename, LessCmp(), type1()); break; case CHECK_DESC: if (dlg->m_Format1) CheckOrder(dlg->m_Filename, GreaterCmp(), type2()); else CheckOrder(dlg->m_Filename, GreaterCmp(), type1()); break; case DEL_DUP: if (dlg->m_Format1) DelDuplicates(dlg->m_Filename, dlg->m_MemUsage, type2()); else DelDuplicates(dlg->m_Filename, dlg->m_MemUsage, type1()); break; default: AfxMessageBox("Command not known or not implemented"); }; PostMessage(notifywindow->m_hWnd, WM_WORK_THREAD_FINISHED, 0, 0); m_bAutoDelete = TRUE; return CWinThread::Run(); } CStxxlWorkThread::CStxxlWorkThread(int taskid_, CWinGUIDlg * dlg_, CWnd * notifywindow_) : taskid(taskid_), dlg(dlg_), notifywindow(notifywindow_) { } stxxl-1.3.1/test/WinGUI/StxxlWorkThread.h0000644000175000017500000000232510631532342020062 0ustar andreasandreas#pragma once // CStxxlWorkThread class CWinGUIDlg; class CStxxlWorkThread : public CWinThread { DECLARE_DYNCREATE(CStxxlWorkThread) protected: CStxxlWorkThread(); // protected constructor used by dynamic creation public: virtual ~CStxxlWorkThread(); public: enum { FILL_RANDOM, FILL_VALUE, SORT_ASC, SORT_DESC, CHECK_ASC, CHECK_DESC, DEL_DUP, CHECK_DUP}; virtual BOOL InitInstance(); virtual int ExitInstance(); CStxxlWorkThread(int taskid, CWinGUIDlg * dlg, CWnd * notifywindow); protected: DECLARE_MESSAGE_MAP() public: virtual int Run(); protected: template void FillRandom(CString & path, LONGLONG filesize, T dummy); template void FillValue(CString & path, LONGLONG filesize, int value, T dummy); template void Sort(CString & path, unsigned mem_usage, Cmp cmp, T dummy); template void CheckOrder(CString & path, Cmp cmp, T dummy); template void DelDuplicates(CString & path, unsigned mem_usage, T dummy); int taskid; CWinGUIDlg * dlg; CWnd * notifywindow; }; stxxl-1.3.1/test/WinGUI/WinGUI.vcproj0000644000175000017500000001565711260335444017142 0ustar andreasandreas stxxl-1.3.1/test/WinGUI/WinGUI.rc0000644000175000017500000002116510622615152016230 0ustar andreasandreas// Microsoft Visual C++ generated resource script. // #include "resource.h" // Generated Help ID header file #define APSTUDIO_HIDDEN_SYMBOLS #include "resource.hm" #undef APSTUDIO_HIDDEN_SYMBOLS #define APSTUDIO_READONLY_SYMBOLS ///////////////////////////////////////////////////////////////////////////// // // Generated from the TEXTINCLUDE 2 resource. // #include "afxres.h" ///////////////////////////////////////////////////////////////////////////// #undef APSTUDIO_READONLY_SYMBOLS ///////////////////////////////////////////////////////////////////////////// // German (Germany) resources #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_DEU) #ifdef _WIN32 LANGUAGE LANG_GERMAN, SUBLANG_GERMAN #pragma code_page(1252) #endif //_WIN32 #ifdef APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// // // TEXTINCLUDE // 1 TEXTINCLUDE BEGIN "resource.h\0" END 2 TEXTINCLUDE BEGIN "#include ""afxres.h""\r\n" "\0" END 3 TEXTINCLUDE BEGIN "#define _AFX_NO_SPLITTER_RESOURCES\r\n" "#define _AFX_NO_OLE_RESOURCES\r\n" "#define _AFX_NO_TRACKER_RESOURCES\r\n" "#define _AFX_NO_PROPERTY_RESOURCES\r\n" "\r\n" "#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r\n" "LANGUAGE 9, 1\r\n" "#pragma code_page(1252)\r\n" "#include ""res\\WinGUI.rc2"" // non-Microsoft Visual C++ edited resources\r\n" "#include ""afxres.rc"" // Standard components\r\n" "#endif\r\n" "\0" END #endif // APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// // // Icon // // Icon with lowest ID value placed first to ensure application icon // remains consistent on all systems. IDR_MAINFRAME ICON "res\\WinGUI.ico" ///////////////////////////////////////////////////////////////////////////// // // Dialog // IDD_WORKDIALOG DIALOGEX 0, 0, 188, 42 STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN CTEXT "Working ...",IDC_MESSAGE1,7,15,174,8 END ///////////////////////////////////////////////////////////////////////////// // // DESIGNINFO // #ifdef APSTUDIO_INVOKED GUIDELINES DESIGNINFO BEGIN IDD_WORKDIALOG, DIALOG BEGIN LEFTMARGIN, 7 RIGHTMARGIN, 181 TOPMARGIN, 7 BOTTOMMARGIN, 35 END END #endif // APSTUDIO_INVOKED #endif // German (Germany) resources ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// // English (U.S.) resources #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) #ifdef _WIN32 LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US #pragma code_page(1252) #endif //_WIN32 ///////////////////////////////////////////////////////////////////////////// // // Dialog // IDD_ABOUTBOX DIALOGEX 0, 0, 235, 55 STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "About WinGUI" FONT 8, "MS Shell Dlg", 0, 0, 0x1 BEGIN ICON IDR_MAINFRAME,IDC_STATIC,11,17,20,20 LTEXT "WinGUI Version 1.0",IDC_STATIC,40,10,119,8,SS_NOPREFIX LTEXT "Copyright (C) 2005 Roman Dementiev",IDC_STATIC,40,25, 188,8 DEFPUSHBUTTON "OK",IDOK,178,7,50,16,WS_GROUP END IDD_WINGUI_DIALOG DIALOGEX 0, 0, 275, 338 STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU EXSTYLE WS_EX_APPWINDOW CAPTION "Using Stxxl in Windows GUI/MFC applications" FONT 8, "MS Shell Dlg", 0, 0, 0x1 BEGIN DEFPUSHBUTTON "E&xit",IDOK,218,315,50,16 GROUPBOX "Create File",IDC_STATIC,7,88,261,79 PUSHBUTTON "Go!",IDC_FILLRANDOMBUTTON,208,128,50,14,0,0, HIDC_FILLRANDOMBUTTON LTEXT "Filename",IDC_STATIC,19,22,29,8 EDITTEXT IDC_FILENAMEEDIT,62,19,136,14,ES_AUTOHSCROLL PUSHBUTTON "Choose",IDC_FILENAMEBUTTON,208,19,50,14 LTEXT "Fill with random integer keys",IDC_STATIC,21,133,92,8 LTEXT "Fill with integer key",IDC_STATIC,21,148,62,8 EDITTEXT IDC_INTEGERKEYEDIT,103,144,86,14,ES_RIGHT | ES_AUTOHSCROLL PUSHBUTTON "Go!",IDC_FILLVALUEBUTTON,208,144,50,14,0,0, HIDC_FILLVALUEBUTTON LTEXT "Sort in ascending order",IDC_STATIC,23,186,75,8 LTEXT "File format",IDC_STATIC,20,50,35,8 CONTROL "4-bytes key, 12-bytes info",IDC_FORMAT1RADIO,"Button", BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP,64,43,101,10 CONTROL "4-bytes key, 28-bytes info",IDC_FORMAT2RADIO,"Button", BS_AUTORADIOBUTTON,64,58,101,10 LTEXT "File size",IDC_STATIC,21,109,26,8 EDITTEXT IDC_FILESIZEEDIT,104,106,59,14,ES_RIGHT | ES_AUTOHSCROLL | ES_NUMBER LTEXT "x 4KB =",IDC_STATIC,167,109,26,8 GROUPBOX "Sort",IDC_STATIC,7,171,261,76 PUSHBUTTON "Go!",IDC_SORTASCBUTTON,208,179,50,14,0,0, HIDC_SORTASCBUTTON LTEXT "Sort in descending order",IDC_STATIC,24,200,79,8 PUSHBUTTON "Go!",IDC_SORTDESCBUTTON4,208,195,50,14,0,0, HIDC_SORTDESCBUTTON4 LTEXT "Check ascending order",IDC_STATIC,24,215,74,8 LTEXT "Check descending order",IDC_STATIC,24,229,78,8 PUSHBUTTON "Go!",IDC_CHECKASCBUTTON,208,210,50,14,0,0, HIDC_CHECKASCBUTTON PUSHBUTTON "Go!",IDC_CHECKDESCBUTTON,208,225,50,14,0,0, HIDC_CHECKDESCBUTTON GROUPBOX "Scan",IDC_STATIC,7,253,261,47 LTEXT "Scan and remove duplicates",IDC_STATIC,24,270,90,8 PUSHBUTTON "Go!",IDC_REMDUPLBUTTON,208,265,50,14,0,0, HIDC_REMDUPLBUTTON LTEXT "Scan and check for duplicates",IDC_STATIC,24,284,96,8 PUSHBUTTON "Go!",IDC_CHECKDUPLBUTTON,208,281,50,14,WS_DISABLED,0, HIDC_CHECKDUPLBUTTON LTEXT "Internal memory to use",IDC_STATIC,21,75,76,8 EDITTEXT IDC_MEMUSAGEEDIT,103,73,83,14,ES_RIGHT | ES_AUTOHSCROLL | ES_NUMBER LTEXT "MBytes",IDC_STATIC,194,76,24,8 EDITTEXT IDC_FILESIZEEDITMB,196,106,42,14,ES_RIGHT | ES_AUTOHSCROLL | ES_READONLY | ES_NUMBER LTEXT "MBytes",IDC_STATIC,241,108,24,8 END ///////////////////////////////////////////////////////////////////////////// // // Version // VS_VERSION_INFO VERSIONINFO FILEVERSION 1,0,0,1 PRODUCTVERSION 1,0,0,1 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L #else FILEFLAGS 0x0L #endif FILEOS 0x4L FILETYPE 0x1L FILESUBTYPE 0x0L BEGIN BLOCK "StringFileInfo" BEGIN BLOCK "040904e4" BEGIN VALUE "CompanyName", "TODO: " VALUE "FileDescription", "TODO: " VALUE "FileVersion", "1.0.0.1" VALUE "InternalName", "WinGUI.exe" VALUE "LegalCopyright", "TODO: (c) . All rights reserved." VALUE "OriginalFilename", "WinGUI.exe" VALUE "ProductName", "TODO: " VALUE "ProductVersion", "1.0.0.1" END END BLOCK "VarFileInfo" BEGIN VALUE "Translation", 0x409, 1252 END END ///////////////////////////////////////////////////////////////////////////// // // DESIGNINFO // #ifdef APSTUDIO_INVOKED GUIDELINES DESIGNINFO BEGIN IDD_ABOUTBOX, DIALOG BEGIN LEFTMARGIN, 7 RIGHTMARGIN, 228 TOPMARGIN, 7 BOTTOMMARGIN, 48 END IDD_WINGUI_DIALOG, DIALOG BEGIN LEFTMARGIN, 7 RIGHTMARGIN, 268 TOPMARGIN, 7 BOTTOMMARGIN, 331 END END #endif // APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// // // String Table // STRINGTABLE BEGIN IDS_ABOUTBOX "&About WinGUI..." END #endif // English (U.S.) resources ///////////////////////////////////////////////////////////////////////////// #ifndef APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// // // Generated from the TEXTINCLUDE 3 resource. // #define _AFX_NO_SPLITTER_RESOURCES #define _AFX_NO_OLE_RESOURCES #define _AFX_NO_TRACKER_RESOURCES #define _AFX_NO_PROPERTY_RESOURCES #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) LANGUAGE 9, 1 #pragma code_page(1252) #include "res\WinGUI.rc2" // non-Microsoft Visual C++ edited resources #include "afxres.rc" // Standard components #endif ///////////////////////////////////////////////////////////////////////////// #endif // not APSTUDIO_INVOKED stxxl-1.3.1/test/WinGUI/WinGUI.suo0000644000175000017500000007400011260335444016430 0ustar andreasandreasࡱ>  .$ !"#%+&'()*,-/03456789:1Root Entry@@BProjInfoExTaskListUserTasks$)IToolboxService  01 "#;&'()*+,-.:3<=?@Aqrstuvwxyz{|}~Joϡ@@RoچC Device ControlsCrystal ReportsData XML Schema Dialog EditorMobile Web Forms Web Forms Components Windows FormsHTMLClipboard RingGeneralpC:\Users\Johannes Singler\CoIVSMDPropertyBrowser**ResEdit.opt2pDebuggerWatches DebuggerBreakpoints(|DebuggerExceptions&DebuggerFindSource& DebuggerFindSymbol&DebuggerMemoryWindows,TxC:\Programme\Microsoft Visual Studio .NET 2003\Vc7\crt\src\C:\Programme\Microsoft Visual Studio .NET 2003\Vc7\atlmfc\src\mfc\C:\Programme\Microsoft Visual Studio .NET 2003\Vc7\atlmfc\src\atl\xf:\dd\vctoolC:\Users\Johannes Singler\Code\Sd '[\{D3Dͫ4ᆳͫ4ᆳMultiStartupProj=;4{D3DE8D18-0A0A-4884-869A-B8C3AF838CF8}.dwStartupOpt=;StartupProjExternalFilesProjectContents: +DocumentWindowPositions0DocumentWindowUserData. SolutionConfiguration,ect=&{D3DE8D18-0A0A-4884-869A-B8C3AF838CF8};?{D3DE8D18-0A0A-4884-869A-B8C3AF838CF8}.Release|Win32.fBatchBld=;={D3DE8D18-0A0A-4884-869A-B8C3AF838CF8}.Debug|Win32.fBatchBld=;4{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3NSܾ M%%ү##G}'bm4l #O¤EObjMgrContentsVClassViewContents$ProjExplorerState$ !hUnloadedProjects"WinGUI%ү##G}'bm4l #O¤EQ C:\Users\Johannes Singler\Code\STXXL Trunk\test\WinGUI\WinGUI.vcprojC:\Users\Johannes SinDebug|Win32DebugSettings$Bookmarks V001.01\async_sched... ....... .,GenWinGUI$lTaskListShortcuts$/VsToolboxService"CObjMgrContentsV8"4eralConfigSettingsVCBscMakeTool(EndConfigPropertiesRelease|Win32DebugSettings... ....... .,GeneralConfigSettingsVCBscMakeTool(EndConfigPropertiesMakeToolX dConfigPropertiesMakeToolTXXL Trunk\test\WinGUI\cl WinGU}.dwStartupOpt=; ActiveCfg>c:\stxxl\test\WinGUI\WinGUI.rc BEGINf ENDN4ᆳ4Gͫ4ᆳͫ4ᆳECSPe.cppve:\programme\microsoft visual studio 8\vc\include\iteratorle:\programme\microsoft visual studio 8\vc\include\newc:\Users\Johannes Singler\Code= Debug|Win32;|c:\anbe\test\Wigler\Code\STXXL Trunk\test\WinGUI\WinGUI.vcprojHeader FilesSource Files3DE8D18-0A0ASystem.Collections.Generic.Dictionary`2[[System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.Collections.Hashtable, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561\STXXL Trunk\test\WinGUI\stdafx.dug ;<{D3Dcpp.re:\programme\microsoft visual studio 8\vc\include\memory<c:\stxxl\algo\test_ksort1.cpp8c:\stxxl\containers\pager.hHiddenSlnFolders"OutliningStateDir$2BookmarkState%(OutliningState1 o$Pc:\stxxl\containers\test_map_random.cpp re:\programme\microsoft visual studio 8\vc\include\vectorFc:\stxxl\containers\test_queue.cpppe:\programme\microsoft visual studio 8\vc\include\xhash c:\users\johannes singler\code\stxxl trunk\include\stxxl\bits\io\wbtl_file.h0c:\Users\Johannes Singler\Code\STXXL Trunk\test\WinGUI\UserTypes.h)4c:\stxxl\mng\write_pool.hPc:\stxxl\containers\test_migr_stack.cpp0c:\stxxl\common\utils.hc:\users\johannes singler\code\stxxl trunk\include\stxxl\bits\io\request.h-c:\Users\Johannes Singler\Code\STXXL Trunk\test\WinGUI\StxxlWorkThread.cpp+Bc:\stxxl\containers\test_map.cppc:\users\johannes singler\code\stxxl trunk\include\stxxl\bits\algo\sort.h28c:\stxxl\containers\stack.hRc:\stxxl\containers\btree\iterator_map.h"Rc:\stxxl\containers\test_many_stacks.cpp&c:\stxxl\mng\mng.h*c:\stxxl\io\iobase.h4c:\stxxl\containers\map.h!Fc:\stxxl\containers\test_deque.cppHc:\stxxl\containers\test_vector.cpp&Nc:\stxxl\containers\btree\node_cache.h c:\users\johannes singler\code\stxxl trunk\include\stxxl\bits\common\utils.h*8c:\stxxl\containers\deque.hc:\users\johannes singler\code\stxxl trunk\include\stxxl\bits\io\file.h$Bookmarks V001.01mme\Microsof7 `tudio .NET 2003\Vc7\atOutliningState45"pOutliningState44"OutliningState43" OutliningState46"#c:\users\johannes singler\code\stxxl trunk\include\stxxl\bits\io\request.hD:M 23DBILCMPjQTU-Wsx!: ( //' YK4&&#4#*4!2""4#'(8+,-/0457:G<AB"D8EIJ'QS^_hcTeqrhvEw~ITI7 c:\Users\Johannes Singler\Code\STXXL Trunk\test\WinGUI\WinGUI.hӡc=c:\Users\Johannes Singler\Code\STXXL Trunk\test\WinGUI\StxxlWorkThread.cppEc:\Users\Johannes Singler\Code\STXXL Trunk\test\WinGUI\stdafx.cppﭩc:\Users\Johannes Singler\Code\STXXL Trunk\test\WinGUI\UserTypeOutliningState41"!OutliningState42".OutliningState47"'OutliningState51"&$ s.h̒,   ,  # %6),-014'66:=>ABE8GGc:\users\johannes singler\code\stxxl trunk\include\stxxl\bits\common\utils.h—  !$+%#24586N7!9:B;'>3?@VANOX[\b6Ge7i!,##-/$<*6  '5 $%B'.(-/4169;8?C8FJ Lc:\users\johannes singler\code\stxxl trunk\include\stxxl\bits\singleton.h 1&,.71;==E Mc:\users\johannes singler\code\stxxl trunk\include\stxxl\bits\io\file.hM #"*+-.014<?@]1_`ah1kluv\{\1"3HBYj( U c:\users\johannes singler\code\stxxl trunk\include\stxxl\bits\io\syscall_file.h~c:\users\johannes singler\code\stxxl trunk\include\stxxl\bits\algo\sort.h$1 9 <1>[F I@KOutliningState53"(OutliningState50"LOutliningState49""%0OutliningState48"6NV `Ob6i l*do{ )n:#v"f!*+,637?EHq_,,|i.2$4%501N/OZRVc:\users\johannes singler\code\stxxl trunk\include\stxxl\bits\mng\mng.hշag  :@ FN OX\](^bc:dCeij:k<lpq9s8twx"z1{~%; 64 4!4% 4! 4!    4 "#$%%(),./?179;*>&@C3EHy~7Q4B@# "&M';$0$4;$<2= AJBIc:\users\johannes singler\code\stxxl trunk\include\stxxl\bits\io\wbtl_file.h׎ 1B5)A D=FH)Jbfc:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\crt\src\crt0msg.cnm OutliningState52"hXmlPackageOptions$ WpfDesigner-E58C2A8B*>kFAE04EC1-301F-11D3_ProjState:5    de\STXXL Trunk\test\WinGUI\s\crt_bld\self_x86\crt\prebuild\eh\unhandld.cpprf:\dd\vctools\crt_bld\self_x86\crt\prebuild\eh\hooks.cppI C:\Users\Johannes Singler\Code\STXXL Trunk\test\WinGUI\libstxxl.lib C:\Users\Johannes Singler\Code\STXXL Trunk\test\WinGUI\msvcrtd.lib C:\Users\Johannes Singler\Code\STXXL Trunk\test\WinGUI\WinGUI cl libstxxl.lib Debug\WinGUI.exe C:\Users\Johannes Singler\Code\STXXL Trunk\test\WinGUI\Debug\WinGUI.exe msvcrtd.lib 934e089]]VersionComparerHashSizeSystem.Collections.Generic.GenericEqualityComparer`1[[System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]] System.Collections.Generic.GenericEqualityComparer`1[[System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]] 36c:\stxxl\io\syscall_file.h(*c:\stxxl\mng\mng.cpp@c:\stxxl\common\simple_vector.h%6c:\stxxl\mng\test_mng1.cpp:c:\stxxl\containers\vector.h#te:\programme\microsoft visual studio 8\vc\include\xmemoryBc:\stxxlude\list c:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\crt\src\crt0msg.c4c:\users\johannes singler\code\stxxl trunk\include\stxxl\bits\singleton.h/Dc:\stxxl\containers\btree\btree.h Hc:\stxxl\containers\test_pqueue.cppbits\mng\mng.h6Bc:\stxxl\algo\async_schedule.cppve:\programme\microsoft visual studio 8\vc\include\iteratorle:\programme\microsoft visual studio 8\vc\include\newc:\Users\Johannes Singler\Code\STXXL Trunk\test\WinGUI\stdafx.cpp.re:\programme\microsoft visual studio 8\vc\include\memory<c:\stxxl\algo\test_ksort1.cpp8c:\stxxl\containers\pager.h$Pc:\stxxl\containers\test_map_random.cpp re:\programme\microsoft visual studio 8\vc\include\vectorFc:\stxxl\containers\test_queue.cpppe:\programme\microsoft visual studio 8\vc\include\xhash c:\users\johannes singler\code\stxxl trunk\include\stxxl\bits\io\wbtl_file.h0c:\Users\Johannes Singler\Code\STXXL Trunk\test\WinGUI\UserTypes.h)4c:\stxxl\mng\write_pool.hPc:\stxxl\containers\test_migr_stack.cpp0c:\stxxl\common\utils.hc:\users\johannes singler\code\stxxl trunk\include\stxxl\bits\io\request.h-c:\Users\Johannes Singler\Code\STXXL Trunk\test\WinGUI\StxxlWorkThread.cpp+Bc:\stxxl\containers\test_map.cppc:\users\johannes singler\code\stxxl trunk\include\stxxl\bits\algo\sort.h28c:\stxxl\containers\stack.hRc:\stxxl\containers\btree\iterator_map.h"Rc:\stxxl\containers\test_many_stacks.cpp&c:\stxxl\mng\mng.h*c:\stxxl\io\iobase.h4c:\stxxl\containers\map.h!Fc:\stxxl\containers\test_deque.cppHc:\stxxl\containers\test_vector.cpp&Nc:\stxxl\containers\btree\node_cache.h c:\users\johannes singler\code\stxxl trunk\include\stxxl\bits\common\utils.h*8c:\stxxl\containers\deque.hc:\users\johannes singler\code\stxxl trunk\include\stxxl\bits\io\file.h36c:\stxxl\io\syscall_file.h(*c:\stxxl\mng\mng.cpp@c:\stxxl\common\simple_vector.h%6c:\stxxl\mng\test_mng1.cpp:c:\stxxl\containers\vector.h#te:\programme\microsoft visual studio 8\vc\include\xmemoryBc:\stxxl\containers\btree\leaf.h 0c:\stxxl\algo\adaptor.h'c:\Users\Johannes Singler\Code\STXXL Trunk\test\WinGUI\WinGUI.h,te:\programme\microsoft visual studio 8\vc\include\xstringc:\users\johannes singler\code\stxxl trunk\include\stxxl\bits\mng\mng.h1vE:\Programme\Microsoft Visual Studio 8\VC\include\xutility"c:\stxxl\io\io.hPc:\stxxl\containers\btree\btree_pager.hc:\users\johannes singler\code\stxxl trunk\include\stxxl\bits\io\syscall_file.h5ne:\programme\microsoft visual studio 8\vc\inclstxxl-1.3.1/test/WinGUI/WinGUIDlg.cpp0000644000175000017500000002075211202521435017031 0ustar andreasandreas// WinGUIDlg.cpp : implementation file // #include "stdafx.h" #include "WinGUI.h" #include "WinGUIDlg.h" #include ".\winguidlg.h" #include "WorkDialog.h" #include "StxxlWorkThread.h" #include "UserTypes.h" #ifdef _DEBUG #define new DEBUG_NEW #endif // CAboutDlg dialog used for App About class CAboutDlg : public CDialog { public: CAboutDlg(); // Dialog Data enum { IDD = IDD_ABOUTBOX }; protected: virtual void DoDataExchange(CDataExchange * pDX); // DDX/DDV support // Implementation protected: DECLARE_MESSAGE_MAP() }; CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD) { } void CAboutDlg::DoDataExchange(CDataExchange * pDX) { CDialog::DoDataExchange(pDX); } BEGIN_MESSAGE_MAP(CAboutDlg, CDialog) END_MESSAGE_MAP() // CWinGUIDlg dialog CWinGUIDlg::CWinGUIDlg(CWnd * pParent /*=NULL*/) : CDialog(CWinGUIDlg::IDD, pParent) , m_Filename(_T("c:\\myfile")) , m_Format1(FALSE) , m_Filesize(LONGLONG(1024) * LONGLONG(512 / 4)) // 1 GiB , m_Key(555) , m_MemUsage(128) , m_FilesizeMB(0) { m_FilesizeMB = m_Filesize / 256; m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); } void CWinGUIDlg::DoDataExchange(CDataExchange * pDX) { CDialog::DoDataExchange(pDX); DDX_Text(pDX, IDC_FILENAMEEDIT, m_Filename); DDX_Radio(pDX, IDC_FORMAT1RADIO, m_Format1); DDX_Text(pDX, IDC_FILESIZEEDIT, m_Filesize); DDX_Text(pDX, IDC_FILESIZEEDITMB, m_FilesizeMB); DDX_Text(pDX, IDC_INTEGERKEYEDIT, m_Key); DDX_Text(pDX, IDC_MEMUSAGEEDIT, m_MemUsage); } BEGIN_MESSAGE_MAP(CWinGUIDlg, CDialog) ON_WM_SYSCOMMAND() ON_WM_PAINT() ON_WM_QUERYDRAGICON() //}}AFX_MSG_MAP ON_BN_CLICKED(IDCANCEL, OnBnClickedCancel) ON_BN_CLICKED(IDOK, OnBnClickedOk) ON_BN_CLICKED(IDC_FILENAMEBUTTON, OnBnClickedFilenamebutton) ON_BN_CLICKED(IDC_FILLRANDOMBUTTON, OnBnClickedFillrandombutton) ON_EN_UPDATE(IDC_FILESIZEEDIT, OnEnUpdateFilesizeedit) // ON_EN_CHANGE(IDC_FILESIZEEDIT, OnEnChangeFilesizeedit) ON_BN_CLICKED(IDC_FILLVALUEBUTTON, OnBnClickedFillvaluebutton) ON_BN_CLICKED(IDC_SORTASCBUTTON, OnBnClickedSortascbutton) ON_BN_CLICKED(IDC_SORTDESCBUTTON4, OnBnClickedSortdescbutton4) ON_BN_CLICKED(IDC_CHECKASCBUTTON, OnBnClickedCheckascbutton) ON_BN_CLICKED(IDC_CHECKDESCBUTTON, OnBnClickedCheckdescbutton) ON_BN_CLICKED(IDC_REMDUPLBUTTON, OnBnClickedRemduplbutton) //ON_BN_CLICKED(IDC_CHECKDUPLBUTTON, OnBnClickedCheckduplbutton) END_MESSAGE_MAP() // CWinGUIDlg message handlers BOOL CWinGUIDlg::OnInitDialog() { CDialog::OnInitDialog(); // Add "About..." menu item to system menu. // IDM_ABOUTBOX must be in the system command range. ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX); ASSERT(IDM_ABOUTBOX < 0xF000); CMenu * pSysMenu = GetSystemMenu(FALSE); if (pSysMenu != NULL) { CString strAboutMenu; strAboutMenu.LoadString(IDS_ABOUTBOX); if (!strAboutMenu.IsEmpty()) { pSysMenu->AppendMenu(MF_SEPARATOR); pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu); } } // Set the icon for this dialog. The framework does this automatically // when the application's main window is not a dialog SetIcon(m_hIcon, TRUE); // Set big icon SetIcon(m_hIcon, FALSE); // Set small icon // TODO: Add extra initialization here return TRUE; // return TRUE unless you set the focus to a control } void CWinGUIDlg::OnSysCommand(UINT nID, LPARAM lParam) { if ((nID & 0xFFF0) == IDM_ABOUTBOX) { CAboutDlg dlgAbout; dlgAbout.DoModal(); } else { CDialog::OnSysCommand(nID, lParam); } } // If you add a minimize button to your dialog, you will need the code below // to draw the icon. For MFC applications using the document/view model, // this is automatically done for you by the framework. void CWinGUIDlg::OnPaint() { if (IsIconic()) { CPaintDC dc(this); // device context for painting SendMessage(WM_ICONERASEBKGND, reinterpret_cast(dc.GetSafeHdc()), 0); // Center icon in client rectangle int cxIcon = GetSystemMetrics(SM_CXICON); int cyIcon = GetSystemMetrics(SM_CYICON); CRect rect; GetClientRect(&rect); int x = (rect.Width() - cxIcon + 1) / 2; int y = (rect.Height() - cyIcon + 1) / 2; // Draw the icon dc.DrawIcon(x, y, m_hIcon); } else { CDialog::OnPaint(); } } // The system calls this function to obtain the cursor to display while the user drags // the minimized window. HCURSOR CWinGUIDlg::OnQueryDragIcon() { return static_cast(m_hIcon); } void CWinGUIDlg::OnBnClickedCancel() { // TODO: Add your control notification handler code here OnCancel(); } void CWinGUIDlg::OnBnClickedOk() { // TODO: Add your control notification handler code here OnOK(); } void CWinGUIDlg::OnBnClickedFilenamebutton() { // TODO: Add your control notification handler code here UpdateData(); CFileDialog FileDialog(TRUE, NULL, LPCTSTR(m_Filename), OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, 0, this); if (FileDialog.DoModal() == IDOK) { m_Filename = FileDialog.GetPathName(); UpdateData(FALSE); } } void CWinGUIDlg::OnBnClickedFillrandombutton() { // TODO: Add your control notification handler code here UpdateData(); CWorkDialog WorkDialog; CStxxlWorkThread * Thread = new CStxxlWorkThread(CStxxlWorkThread::FILL_RANDOM, this, &WorkDialog); WorkDialog.SetThread(Thread); WorkDialog.DoModal(); } void CWinGUIDlg::OnEnUpdateFilesizeedit() { // TODO: If this is a RICHEDIT control, the control will not // send this notification unless you override the CDialog::OnInitDialog() // function to send the EM_SETEVENTMASK message to the control // with the ENM_UPDATE flag ORed into the lParam mask. // TODO: Add your control notification handler code here UpdateData(); m_FilesizeMB = m_Filesize / 256; UpdateData(FALSE); } //void CWinGUIDlg::OnEnChangeFilesizeedit() //{ // // TODO: If this is a RICHEDIT control, the control will not // // send this notification unless you override the CDialog::OnInitDialog() // // function and call CRichEditCtrl().SetEventMask() // // with the ENM_CHANGE flag ORed into the mask. // // // TODO: Add your control notification handler code here // //} void CWinGUIDlg::OnBnClickedFillvaluebutton() { // TODO: Add your control notification handler code here UpdateData(); CWorkDialog WorkDialog; CStxxlWorkThread * Thread = new CStxxlWorkThread(CStxxlWorkThread::FILL_VALUE, this, &WorkDialog); WorkDialog.SetThread(Thread); WorkDialog.DoModal(); } void CWinGUIDlg::OnBnClickedSortascbutton() { // TODO: Add your control notification handler code here UpdateData(); CWorkDialog WorkDialog; CStxxlWorkThread * Thread = new CStxxlWorkThread(CStxxlWorkThread::SORT_ASC, this, &WorkDialog); WorkDialog.SetThread(Thread); WorkDialog.DoModal(); } void CWinGUIDlg::OnBnClickedSortdescbutton4() { // TODO: Add your control notification handler code here UpdateData(); CWorkDialog WorkDialog; CStxxlWorkThread * Thread = new CStxxlWorkThread(CStxxlWorkThread::SORT_DESC, this, &WorkDialog); WorkDialog.SetThread(Thread); WorkDialog.DoModal(); } void CWinGUIDlg::OnBnClickedCheckascbutton() { // TODO: Add your control notification handler code here UpdateData(); CWorkDialog WorkDialog; CStxxlWorkThread * Thread = new CStxxlWorkThread(CStxxlWorkThread::CHECK_ASC, this, &WorkDialog); WorkDialog.SetThread(Thread); WorkDialog.DoModal(); } void CWinGUIDlg::OnBnClickedCheckdescbutton() { // TODO: Add your control notification handler code here UpdateData(); CWorkDialog WorkDialog; CStxxlWorkThread * Thread = new CStxxlWorkThread(CStxxlWorkThread::CHECK_DESC, this, &WorkDialog); WorkDialog.SetThread(Thread); WorkDialog.DoModal(); } void CWinGUIDlg::OnBnClickedRemduplbutton() { // TODO: Add your control notification handler code here UpdateData(); CWorkDialog WorkDialog; CStxxlWorkThread * Thread = new CStxxlWorkThread(CStxxlWorkThread::DEL_DUP, this, &WorkDialog); WorkDialog.SetThread(Thread); WorkDialog.DoModal(); } //void CWinGUIDlg::OnBnClickedCheckduplbutton() //{ // // TODO: Add your control notification handler code here // UpdateData(); // CWorkDialog WorkDialog; // CStxxlWorkThread * Thread = new CStxxlWorkThread(CStxxlWorkThread::CHECK_DUP,this,&WorkDialog); // WorkDialog.SetThread(Thread); // WorkDialog.DoModal(); //} stxxl-1.3.1/test/WinGUI/stdafx.cpp0000644000175000017500000000030710622615152016570 0ustar andreasandreas// stdafx.cpp : source file that includes just the standard includes // WinGUI.pch will be the pre-compiled header // stdafx.obj will contain the pre-compiled type information #include "stdafx.h" stxxl-1.3.1/test/WinGUI/ReadMe.txt0000644000175000017500000000755710622615152016507 0ustar andreasandreas================================================================================ MICROSOFT FOUNDATION CLASS LIBRARY : WinGUI Project Overview =============================================================================== The application wizard has created this WinGUI application for you. This application not only demonstrates the basics of using the Microsoft Foundation Classes but is also a starting point for writing your application. This file contains a summary of what you will find in each of the files that make up your WinGUI application. WinGUI.vcproj This is the main project file for VC++ projects generated using an application wizard. It contains information about the version of Visual C++ that generated the file, and information about the platforms, configurations, and project features selected with the application wizard. WinGUI.h This is the main header file for the application. It includes other project specific headers (including Resource.h) and declares the CWinGUIApp application class. WinGUI.cpp This is the main application source file that contains the application class CWinGUIApp. WinGUI.rc This is a listing of all of the Microsoft Windows resources that the program uses. It includes the icons, bitmaps, and cursors that are stored in the RES subdirectory. This file can be directly edited in Microsoft Visual C++. Your project resources are in 1033. res\WinGUI.ico This is an icon file, which is used as the application's icon. This icon is included by the main resource file WinGUI.rc. res\WinGUI.rc2 This file contains resources that are not edited by Microsoft Visual C++. You should place all resources not editable by the resource editor in this file. ///////////////////////////////////////////////////////////////////////////// The application wizard creates one dialog class: WinGUIDlg.h, WinGUIDlg.cpp - the dialog These files contain your CWinGUIDlg class. This class defines the behavior of your application's main dialog. The dialog's template is in WinGUI.rc, which can be edited in Microsoft Visual C++. ///////////////////////////////////////////////////////////////////////////// Other standard files: StdAfx.h, StdAfx.cpp These files are used to build a precompiled header (PCH) file named WinGUI.pch and a precompiled types file named StdAfx.obj. Resource.h This is the standard header file, which defines new resource IDs. Microsoft Visual C++ reads and updates this file. WinGUI.manifest Application manifest files are used by Windows XP to describe an applications dependency on specific versions of Side-by-Side assemblies. The loader uses this information to load the appropriate assembly from the assembly cache or private from the application. The Application manifest maybe included for redistribution as an external .manifest file that is installed in the same folder as the application executable or it may be included in the executable in the form of a resource. ///////////////////////////////////////////////////////////////////////////// Other notes: The application wizard uses "TODO:" to indicate parts of the source code you should add to or customize. If your application uses MFC in a shared DLL, and your application is in a language other than the operating system's current language, you will need to copy the corresponding localized resources MFC70XXX.DLL from the Microsoft Visual C++ CD-ROM under the Win\System directory to your computer's system or system32 directory, and rename it to be MFCLOC.DLL. ("XXX" stands for the language abbreviation. For example, MFC70DEU.DLL contains resources translated to German.) If you don't do this, some of the UI elements of your application will remain in the language of the operating system. ///////////////////////////////////////////////////////////////////////////// stxxl-1.3.1/test/WinGUI/resource.h0000644000175000017500000000270310631532342016574 0ustar andreasandreas//{{NO_DEPENDENCIES}} // Microsoft Visual C++ generated include file. // Used by WinGUI.rc // #define IDM_ABOUTBOX 0x0010 #define IDD_ABOUTBOX 100 #define IDS_ABOUTBOX 101 #define IDD_WINGUI_DIALOG 102 #define IDR_MAINFRAME 128 #define IDD_WORKDIALOG 129 #define IDC_FILLRANDOMBUTTON 1000 #define IDC_FILENAMEEDIT 1001 #define IDC_FILENAMEBUTTON 1002 #define IDC_INTEGERKEYEDIT 1003 #define IDC_FILLVALUEBUTTON 1004 #define IDC_FORMAT1RADIO 1005 #define IDC_FORMAT2RADIO 1006 #define IDC_FILESIZEEDIT 1007 #define IDC_FILESIZEEDIT2 1008 #define IDC_FILESIZEEDITMB 1008 #define IDC_SORTASCBUTTON 1009 #define IDC_MESSAGE1 1009 #define IDC_SORTDESCBUTTON4 1010 #define IDC_CHECKASCBUTTON 1011 #define IDC_CHECKDESCBUTTON 1012 #define IDC_REMDUPLBUTTON 1013 #define IDC_CHECKDUPLBUTTON 1014 #define IDC_MEMUSAGEEDIT 1015 // Next default values for new objects // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 130 #define _APS_NEXT_COMMAND_VALUE 32771 #define _APS_NEXT_CONTROL_VALUE 1010 #define _APS_NEXT_SYMED_VALUE 101 #endif #endif stxxl-1.3.1/algo/0000755000175000017500000000000011536252421013435 5ustar andreasandreasstxxl-1.3.1/algo/test_ksort.cpp0000644000175000017500000000632111200337416016340 0ustar andreasandreas/*************************************************************************** * algo/test_ksort.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2002 Roman Dementiev * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ //! \example algo/test_ksort.cpp //! This is an example of how to use \c stxxl::ksort() algorithm #include #include #include struct my_type { typedef stxxl::uint64 key_type1; key_type1 _key; key_type1 _key_copy; char _data[32 - 2 * sizeof(key_type1)]; key_type1 key() const { return _key; } my_type() : _key(0), _key_copy(0) { } my_type(key_type1 __key) : _key(__key) { } my_type min_value() const { return my_type((std::numeric_limits::min)()); } my_type max_value() const { return my_type((std::numeric_limits::max)()); } }; std::ostream & operator << (std::ostream & o, const my_type & obj) { o << obj._key << " " << obj._key_copy; return o; } struct get_key { typedef my_type::key_type1 key_type; my_type dummy; key_type operator () (const my_type & obj) const { return obj._key; } my_type min_value() const { return my_type((dummy.min_value)()); } my_type max_value() const { return my_type((dummy.max_value)()); } }; bool operator < (const my_type & a, const my_type & b) { return a.key() < b.key(); } int main() { STXXL_MSG("Check config..."); try { stxxl::block_manager::get_instance(); } catch (std::exception & e) { STXXL_MSG("Exception: " << e.what()); abort(); } #if STXXL_PARALLEL_MULTIWAY_MERGE STXXL_MSG("STXXL_PARALLEL_MULTIWAY_MERGE"); #endif unsigned memory_to_use = 32 * 1024 * 1024; typedef stxxl::VECTOR_GENERATOR::result vector_type; const stxxl::int64 n_records = 3 * 32 * stxxl::int64(1024 * 1024) / sizeof(my_type); vector_type v(n_records); stxxl::random_number32 rnd; STXXL_MSG("Filling vector... "); for (vector_type::size_type i = 0; i < v.size(); i++) { v[i]._key = rnd() + 1; v[i]._key_copy = v[i]._key; } STXXL_MSG("Checking order..."); STXXL_MSG(((stxxl::is_sorted(v.begin(), v.end())) ? "OK" : "WRONG")); STXXL_MSG("Sorting..."); stxxl::ksort(v.begin(), v.end(), get_key(), memory_to_use); //stxxl::ksort(v.begin(),v.end(),memory_to_use); STXXL_MSG("Checking order..."); STXXL_MSG(((stxxl::is_sorted(v.begin(), v.end())) ? "OK" : "WRONG")); STXXL_MSG("Checking content..."); my_type prev; for (vector_type::size_type i = 0; i < v.size(); i++) { if (v[i]._key != v[i]._key_copy) { STXXL_MSG("Bug at position " << i); abort(); } if (i > 0 && prev._key == v[i]._key) { STXXL_MSG("Duplicate at position " << i << " key=" << v[i]._key); //abort(); } prev = v[i]; } STXXL_MSG("OK"); return 0; } stxxl-1.3.1/algo/test_sort_all_parameters.cpp0000644000175000017500000001257011202521435021241 0ustar andreasandreas/*************************************************************************** * algo/test_sort_all_parameters.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2002 Roman Dementiev * Copyright (C) 2008 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ //#define PLAY_WITH_OPT_PREF #include #include #include #include #include #include "test_sort_all_parameters.h" #ifndef RECORD_SIZE #define RECORD_SIZE 4 #endif #define MB (1024 * 1024) template void test(stxxl::uint64 data_mem, unsigned memory_to_use) { stxxl::uint64 records_to_sort = data_mem / sizeof(T); typedef stxxl::vector, block_size, alloc_strategy_type> vector_type; vector_type v(records_to_sort); unsigned ndisks = stxxl::config::get_instance()->disks_number(); STXXL_MSG("Sorting " << records_to_sort << " records of size " << sizeof(T)); STXXL_MSG("Total volume " << (records_to_sort * sizeof(T)) / MB << " MiB"); STXXL_MSG("Using " << memory_to_use / MB << " MiB"); STXXL_MSG("Using " << ndisks << " disks"); STXXL_MSG("Using " << alloc_strategy_type::name() << " allocation strategy "); STXXL_MSG("Block size " << vector_type::block_type::raw_size / 1024 << " KiB"); STXXL_MSG("Filling vector..."); stxxl::generate(v.begin(), v.end(), stxxl::random_number32_r(), 32); STXXL_MSG("Sorting vector..."); stxxl::stats_data before(*stxxl::stats::get_instance()); stxxl::sort(v.begin(), v.end(), Cmp(), memory_to_use); stxxl::stats_data after(*stxxl::stats::get_instance()); STXXL_MSG("Checking order..."); STXXL_MSG((stxxl::is_sorted(v.begin(), v.end(), Cmp()) ? "OK" : "WRONG")); STXXL_MSG("Sorting: " << (after - before)); STXXL_MSG("Total: " << *stxxl::stats::get_instance()); } template void test_all_strategies( stxxl::uint64 data_mem, unsigned memory_to_use, int strategy) { switch (strategy) { case 0: test(data_mem, memory_to_use); break; case 1: test(data_mem, memory_to_use); break; case 2: test(data_mem, memory_to_use); break; case 3: test(data_mem, memory_to_use); break; default: STXXL_ERRMSG("Unknown allocation strategy: " << strategy << ", aborting"); abort(); } } int main(int argc, char * argv[]) { if (argc < 6) { STXXL_ERRMSG("Usage: " << argv[0] << " "); return -1; } #if STXXL_PARALLEL_MULTIWAY_MERGE STXXL_MSG("STXXL_PARALLEL_MULTIWAY_MERGE"); #endif stxxl::uint64 data_mem = stxxl::atoint64(argv[1]) * MB; int sort_mem = atoi(argv[2]) * MB; int strategy = atoi(argv[3]); int block_size = atoi(argv[4]); stxxl::set_seed(strtoul(argv[5], NULL, 10)); STXXL_MSG("Seed " << stxxl::get_next_seed()); stxxl::srandom_number32(); typedef my_type my_default_type; switch (block_size) { case 0: test_all_strategies(data_mem, sort_mem, strategy); break; case 1: test_all_strategies(data_mem, sort_mem, strategy); break; case 2: test_all_strategies(data_mem, sort_mem, strategy); break; case 3: test_all_strategies(data_mem, sort_mem, strategy); break; case 4: test_all_strategies(data_mem, sort_mem, strategy); break; case 5: test_all_strategies(data_mem, sort_mem, strategy); break; case 6: test_all_strategies(data_mem, sort_mem, strategy); break; case 7: test_all_strategies(data_mem, sort_mem, strategy); break; case 8: test_all_strategies(data_mem, sort_mem, strategy); break; case 9: test_all_strategies(data_mem, sort_mem, strategy); break; case 10: test_all_strategies(data_mem, sort_mem, strategy); break; case 11: test_all_strategies, 2 * MB>(data_mem, sort_mem, strategy); break; case 12: test_all_strategies, 2 * MB + 4096>(data_mem, sort_mem, strategy); break; case 13: test_all_strategies, 2 * MB + 4096>(data_mem, sort_mem, strategy); break; case 14: test_all_strategies, 2 * MB>(data_mem, sort_mem, strategy); break; default: STXXL_ERRMSG("Unknown block size: " << block_size << ", aborting"); abort(); } return 0; } stxxl-1.3.1/algo/copy_and_sort_file.cpp0000644000175000017500000000653711517776461020034 0ustar andreasandreas/*************************************************************************** * algo/copy_and_sort_file.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2010 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ //! \example algo/copy_and_sort_file.cpp //! This example imports a file into an \c stxxl::vector without copying its //! content and then sorts it using stxxl::sort / stxxl::ksort / ... #include #include #include #include struct my_type { typedef unsigned key_type; key_type _key; char _data[128 - sizeof(key_type)]; key_type key() const { return _key; } my_type() { } my_type(key_type __key) : _key(__key) { } static my_type min_value() { return my_type((std::numeric_limits::min)()); } static my_type max_value() { return my_type((std::numeric_limits::max)()); } }; inline bool operator < (const my_type & a, const my_type & b) { return a.key() < b.key(); } inline bool operator == (const my_type & a, const my_type & b) { return a.key() == b.key(); } struct Cmp { typedef my_type first_argument_type; typedef my_type second_argument_type; typedef bool result_type; bool operator () (const my_type & a, const my_type & b) const { return a < b; } static my_type min_value() { return my_type::min_value(); } static my_type max_value() { return my_type::max_value(); } }; std::ostream & operator << (std::ostream & o, const my_type & obj) { o << obj._key; return o; } int main(int argc, char ** argv) { if (argc < 3) { std::cout << "Usage: " << argv[0] << " infile outfile" << std::endl; return -1; } const unsigned memory_to_use = 512 * 1024 * 1024; const unsigned int block_size = sizeof(my_type) * 4096; typedef stxxl::vector, block_size> vector_type; stxxl::syscall_file in_file(argv[1], stxxl::file::DIRECT | stxxl::file::RDONLY); stxxl::syscall_file out_file(argv[2], stxxl::file::DIRECT | stxxl::file::RDWR | stxxl::file::CREAT); vector_type input(&in_file); vector_type output(&out_file); output.resize(input.size()); #ifdef BOOST_MSVC typedef stxxl::stream::streamify_traits::stream_type input_stream_type; #else typedef __typeof__(stxxl::stream::streamify(input.begin(), input.end())) input_stream_type; #endif input_stream_type input_stream = stxxl::stream::streamify(input.begin(), input.end()); typedef Cmp comparator_type; typedef stxxl::stream::sort sort_stream_type; sort_stream_type sort_stream(input_stream, comparator_type(), memory_to_use); vector_type::iterator o = stxxl::stream::materialize(sort_stream, output.begin(), output.end()); assert(o == output.end()); if (1) { STXXL_MSG("Checking order..."); STXXL_MSG((stxxl::is_sorted(output.begin(), output.end(), comparator_type()) ? "OK" : "WRONG")); } return 0; } // vim: et:ts=4:sw=4 stxxl-1.3.1/algo/test_parallel_sort.cpp0000644000175000017500000002534411535151017020051 0ustar andreasandreas/*************************************************************************** * algo/test_parallel_sort.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2007, 2009 Johannes Singler * Copyright (C) 2008, 2009 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ //! \example algo/test_parallel_sort.cpp //! This is an example of how to use the parallelized sorting algorithm. //! Setting all the parameters in optional, just compiling with either MCSTL //! or parallel mode suffices. #define MCSTL_QUICKSORT_WORKAROUND 0 #if !defined(STXXL_NOT_CONSIDER_SORT_MEMORY_OVERHEAD) #define STXXL_NOT_CONSIDER_SORT_MEMORY_OVERHEAD 0 #endif #include #include #include #include #include #include #include #ifdef __MCSTL__ #include #endif const unsigned long long megabyte = 1024 * 1024; //const int block_size = STXXL_DEFAULT_BLOCK_SIZE(my_type); const int block_size = 4 * megabyte; #define RECORD_SIZE 16 #define MAGIC 123 stxxl::unsigned_type run_size; stxxl::unsigned_type buffer_size; struct my_type { typedef unsigned long long key_type; key_type _key; key_type _load; char _data[RECORD_SIZE - 2 * sizeof(key_type)]; key_type key() const { return _key; } my_type() { } my_type(key_type __key) : _key(__key) { } my_type(key_type __key, key_type __load) : _key(__key), _load(__load) { } void operator = (const key_type & __key) { _key = __key; } void operator = (const my_type & mt) { _key = mt._key; _load = mt._load; } }; bool operator < (const my_type & a, const my_type & b); inline bool operator < (const my_type & a, const my_type & b) { return a.key() < b.key(); } inline bool operator == (const my_type & a, const my_type & b) { return a.key() == b.key(); } inline std::ostream & operator << (std::ostream & o, const my_type & obj) { o << obj._key << "/" << obj._load; return o; } struct cmp_less_key : public std::less { my_type min_value() const { return my_type(std::numeric_limits::min(), MAGIC); } my_type max_value() const { return my_type(std::numeric_limits::max(), MAGIC); } }; typedef stxxl::vector, block_size, STXXL_DEFAULT_ALLOC_STRATEGY> vector_type; stxxl::unsigned_type checksum(vector_type & input) { stxxl::unsigned_type sum = 0; for (vector_type::const_iterator i = input.begin(); i != input.end(); ++i) sum += (*i)._key; return sum; } void linear_sort_normal(vector_type & input) { stxxl::unsigned_type sum1 = checksum(input); stxxl::stats_data stats_begin(*stxxl::stats::get_instance()); double start = stxxl::timestamp(); stxxl::sort(input.begin(), input.end(), cmp_less_key(), run_size); double stop = stxxl::timestamp(); std::cout << stxxl::stats_data(*stxxl::stats::get_instance()) - stats_begin; stxxl::unsigned_type sum2 = checksum(input); std::cout << sum1 << " ?= " << sum2 << std::endl; STXXL_MSG((stxxl::is_sorted(input.begin(), input.end()) ? "OK" : "NOT SORTED")); std::cout << "Linear sorting normal took " << (stop - start) << " seconds." << std::endl; } void linear_sort_streamed(vector_type & input, vector_type & output) { stxxl::unsigned_type sum1 = checksum(input); stxxl::stats_data stats_begin(*stxxl::stats::get_instance()); double start = stxxl::timestamp(); typedef __typeof__(stxxl::stream::streamify(input.begin(), input.end())) input_stream_type; input_stream_type input_stream = stxxl::stream::streamify(input.begin(), input.end()); typedef cmp_less_key comparator_type; comparator_type cl; typedef stxxl::stream::sort sort_stream_type; sort_stream_type sort_stream(input_stream, cl, run_size); vector_type::iterator o = stxxl::stream::materialize(sort_stream, output.begin(), output.end()); assert(o == output.end()); double stop = stxxl::timestamp(); std::cout << stxxl::stats_data(*stxxl::stats::get_instance()) - stats_begin; stxxl::unsigned_type sum2 = checksum(output); std::cout << sum1 << " ?= " << sum2 << std::endl; if (sum1 != sum2) STXXL_MSG("WRONG DATA"); STXXL_MSG((stxxl::is_sorted(output.begin(), output.end(), comparator_type()) ? "OK" : "NOT SORTED")); std::cout << "Linear sorting streamed took " << (stop - start) << " seconds." << std::endl; } int main(int argc, const char ** argv) { if (argc < 6) { std::cout << "Usage: " << argv[0] << " [n in MiB] [p threads] [M in MiB] [sorting algorithm: m | q | qb | s] [merging algorithm: p | s | n]" << std::endl; return -1; } stxxl::config::get_instance(); #if STXXL_PARALLEL_MULTIWAY_MERGE STXXL_MSG("STXXL_PARALLEL_MULTIWAY_MERGE"); #endif unsigned long megabytes_to_process = atoi(argv[1]); int p = atoi(argv[2]); stxxl::unsigned_type memory_to_use = (stxxl::unsigned_type)atoi(argv[3]) * megabyte; run_size = memory_to_use; buffer_size = memory_to_use / 16; #ifdef STXXL_PARALLEL_MODE omp_set_num_threads(p); __gnu_parallel::_Settings parallel_settings(__gnu_parallel::_Settings::get()); parallel_settings.merge_splitting = __gnu_parallel::EXACT; parallel_settings.merge_minimal_n = 10000; parallel_settings.merge_oversampling = 10; parallel_settings.multiway_merge_algorithm = __gnu_parallel::LOSER_TREE; parallel_settings.multiway_merge_splitting = __gnu_parallel::EXACT; parallel_settings.multiway_merge_oversampling = 10; parallel_settings.multiway_merge_minimal_n = 10000; parallel_settings.multiway_merge_minimal_k = 2; if (!strcmp(argv[4], "q")) //quicksort parallel_settings.sort_algorithm = __gnu_parallel::QS; else if (!strcmp(argv[4], "qb")) //balanced quicksort parallel_settings.sort_algorithm = __gnu_parallel::QS_BALANCED; else if (!strcmp(argv[4], "m")) //merge sort parallel_settings.sort_algorithm = __gnu_parallel::MWMS; else /*if(!strcmp(argv[4], "s"))*/ //sequential (default) { parallel_settings.sort_algorithm = __gnu_parallel::QS; parallel_settings.sort_minimal_n = memory_to_use; } if (!strcmp(argv[5], "p")) //parallel { stxxl::SETTINGS::native_merge = false; //parallel_settings.multiway_merge_minimal_n = 1024; //leave as default } else if (!strcmp(argv[5], "s")) //sequential { stxxl::SETTINGS::native_merge = false; parallel_settings.multiway_merge_minimal_n = memory_to_use; //too much to be called } else /*if(!strcmp(argv[5], "n"))*/ //native (default) stxxl::SETTINGS::native_merge = true; parallel_settings.multiway_merge_minimal_k = 2; __gnu_parallel::_Settings::set(parallel_settings); assert(&__gnu_parallel::_Settings::get() != ¶llel_settings); if (0) printf("%d %p: mwms %d, q %d, qb %d", __gnu_parallel::_Settings::get().sort_algorithm, &__gnu_parallel::_Settings::get().sort_algorithm, __gnu_parallel::MWMS, __gnu_parallel::QS, __gnu_parallel::QS_BALANCED); #elif defined(__MCSTL__) mcstl::HEURISTIC::num_threads = p; mcstl::HEURISTIC::force_sequential = false; mcstl::HEURISTIC::merge_splitting = mcstl::HEURISTIC::EXACT; mcstl::HEURISTIC::merge_minimal_n = 10000; mcstl::HEURISTIC::merge_oversampling = 10; mcstl::HEURISTIC::multiway_merge_algorithm = mcstl::HEURISTIC::LOSER_TREE; mcstl::HEURISTIC::multiway_merge_splitting = mcstl::HEURISTIC::EXACT; mcstl::HEURISTIC::multiway_merge_oversampling = 10; mcstl::HEURISTIC::multiway_merge_minimal_n = 10000; mcstl::HEURISTIC::multiway_merge_minimal_k = 2; if (!strcmp(argv[4], "q")) //quicksort mcstl::HEURISTIC::sort_algorithm = mcstl::HEURISTIC::QS; else if (!strcmp(argv[4], "qb")) //balanced quicksort mcstl::HEURISTIC::sort_algorithm = mcstl::HEURISTIC::QS_BALANCED; else if (!strcmp(argv[4], "m")) //merge sort mcstl::HEURISTIC::sort_algorithm = mcstl::HEURISTIC::MWMS; else /*if(!strcmp(argv[4], "s"))*/ //sequential (default) { mcstl::HEURISTIC::sort_algorithm = mcstl::HEURISTIC::QS; mcstl::HEURISTIC::sort_minimal_n = memory_to_use; } if (!strcmp(argv[5], "p")) //parallel { stxxl::SETTINGS::native_merge = false; //mcstl::HEURISTIC::multiway_merge_minimal_n = 1024; //leave as default } else if (!strcmp(argv[5], "s")) //sequential { stxxl::SETTINGS::native_merge = false; mcstl::HEURISTIC::multiway_merge_minimal_n = memory_to_use; //too much to be called } else /*if(!strcmp(argv[5], "n"))*/ //native (default) stxxl::SETTINGS::native_merge = true; mcstl::HEURISTIC::multiway_merge_minimal_k = 2; #endif std::cout << "Sorting " << megabytes_to_process << " MiB of data (" << (megabytes_to_process * megabyte / sizeof(my_type)) << " elements) using " << (memory_to_use / megabyte) << " MiB of internal memory and " << p << " thread(s), block size " << block_size << ", element size " << sizeof(my_type) << std::endl; const stxxl::int64 n_records = stxxl::int64(megabytes_to_process) * stxxl::int64(megabyte) / sizeof(my_type); vector_type input(n_records); stxxl::stats_data stats_begin(*stxxl::stats::get_instance()); double generate_start = stxxl::timestamp(); stxxl::generate(input.begin(), input.end(), stxxl::random_number64(), memory_to_use / STXXL_DEFAULT_BLOCK_SIZE(my_type)); double generate_stop = stxxl::timestamp(); std::cout << stxxl::stats_data(*stxxl::stats::get_instance()) - stats_begin; std::cout << "Generating took " << (generate_stop - generate_start) << " seconds." << std::endl; STXXL_MSG(((stxxl::is_sorted(input.begin(), input.end())) ? "OK" : "NOT SORTED")); { vector_type output(n_records); linear_sort_streamed(input, output); linear_sort_normal(input); } return 0; } // vim: et:ts=4:sw=4 stxxl-1.3.1/algo/test_stable_ksort_all_parameters.cpp0000644000175000017500000001307211525056563022761 0ustar andreasandreas/*************************************************************************** * algo/test_stable_ksort_all_parameters.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2003 Roman Dementiev * Copyright (C) 2008 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ //#define PLAY_WITH_OPT_PREF #include #include #include #include #define KEY_COMPARE #include "test_sort_all_parameters.h" #ifndef RECORD_SIZE #define RECORD_SIZE 128 #endif #define MB (1024 * 1024) template void test(stxxl::uint64 data_mem, unsigned memory_to_use) { stxxl::uint64 records_to_sort = data_mem / sizeof(T); typedef stxxl::vector, block_size, alloc_strategy_type> vector_type; memory_to_use = stxxl::div_ceil(memory_to_use, vector_type::block_type::raw_size) * vector_type::block_type::raw_size; vector_type v(records_to_sort); unsigned ndisks = stxxl::config::get_instance()->disks_number(); STXXL_MSG("Sorting " << records_to_sort << " records of size " << sizeof(T)); STXXL_MSG("Total volume " << (records_to_sort * sizeof(T)) / MB << " MiB"); STXXL_MSG("Using " << memory_to_use / MB << " MiB"); STXXL_MSG("Using " << ndisks << " disks"); STXXL_MSG("Using " << alloc_strategy_type::name() << " allocation strategy "); STXXL_MSG("Block size " << vector_type::block_type::raw_size / 1024 << " KiB"); STXXL_MSG("Filling vector..."); std::generate(v.begin(), v.end(), stxxl::random_number64() _STXXL_FORCE_SEQUENTIAL); //std::generate(v.begin(),v.end(),zero()); STXXL_MSG("Sorting vector..."); stxxl::stats_data before(*stxxl::stats::get_instance()); stxxl::stable_ksort(v.begin(), v.end(), memory_to_use); stxxl::stats_data after(*stxxl::stats::get_instance()); STXXL_MSG("Checking order..."); STXXL_MSG((stxxl::is_sorted(v.begin(), v.end()) ? "OK" : "WRONG")); STXXL_MSG("Sorting: " << (after - before)); STXXL_MSG("Total: " << *stxxl::stats::get_instance()); } template void test_all_strategies( stxxl::uint64 data_mem, unsigned memory_to_use, int strategy) { switch (strategy) { case 0: test(data_mem, memory_to_use); break; case 1: test(data_mem, memory_to_use); break; case 2: test(data_mem, memory_to_use); break; case 3: test(data_mem, memory_to_use); break; default: STXXL_ERRMSG("Unknown allocation strategy: " << strategy << ", aborting"); abort(); } } int main(int argc, char * argv[]) { if (argc < 6) { STXXL_ERRMSG("Usage: " << argv[0] << " "); return -1; } #if STXXL_PARALLEL_MULTIWAY_MERGE STXXL_MSG("STXXL_PARALLEL_MULTIWAY_MERGE"); #endif stxxl::uint64 data_mem = stxxl::atoint64(argv[1]) * MB; int sort_mem = atoi(argv[2]) * MB; int strategy = atoi(argv[3]); int block_size = atoi(argv[4]); stxxl::set_seed(strtoul(argv[5], NULL, 10)); STXXL_MSG("Seed " << stxxl::get_next_seed()); stxxl::srandom_number32(); typedef my_type my_default_type; switch (block_size) { case 0: test_all_strategies(data_mem, sort_mem, strategy); break; case 1: test_all_strategies(data_mem, sort_mem, strategy); break; case 2: test_all_strategies(data_mem, sort_mem, strategy); break; case 3: test_all_strategies(data_mem, sort_mem, strategy); break; case 4: test_all_strategies(data_mem, sort_mem, strategy); break; case 5: test_all_strategies(data_mem, sort_mem, strategy); break; case 6: test_all_strategies(data_mem, sort_mem, strategy); break; case 7: test_all_strategies(data_mem, sort_mem, strategy); break; case 8: test_all_strategies(data_mem, sort_mem, strategy); break; case 9: test_all_strategies(data_mem, sort_mem, strategy); break; case 10: test_all_strategies(data_mem, sort_mem, strategy); break; case 11: test_all_strategies, 2 * MB>(data_mem, sort_mem, strategy); break; case 12: test_all_strategies, 2 * MB + 4096>(data_mem, sort_mem, strategy); break; case 13: test_all_strategies, 2 * MB + 4096>(data_mem, sort_mem, strategy); break; case 14: test_all_strategies, 2 * MB>(data_mem, sort_mem, strategy); break; default: STXXL_ERRMSG("Unknown block size: " << block_size << ", aborting"); abort(); } return 0; } stxxl-1.3.1/algo/GNUmakefile0000644000175000017500000000547511536205566015532 0ustar andreasandreasTOPDIR ?= .. include Makefile.common -include $(TOPDIR)/make.settings.local ENABLE_LONG_COMPILE ?= no TESTS-yes += $(TESTS_NON_MSVC) TESTS-$(ENABLE_LONG_COMPILE) += $(TESTS_LONG_COMPILE) include $(TOPDIR)/Makefile.subdir.gnu test_ksort.$o: CPPFLAGS += -DSTXXL_VERBOSE_LEVEL=1 -DSTXXL_CHECK_ORDER_IN_SORTS test_sort.$o: CPPFLAGS += -DSTXXL_VERBOSE_LEVEL=0 test_bad_cmp.$o: CPPFLAGS += -DSTXXL_VERBOSE_LEVEL=0 test_random_shuffle.$o: CPPFLAGS += -DSTXXL_VERBOSE_LEVEL=0 test_stable_ksort_all_parameters.$o: CPPFLAGS += -DSTXXL_VERBOSE_STABLE_KSORT=STXXL_VERBOSE0 -DSTXXL_VERBOSE_LEVEL=0 -DSTXXL_CHECK_ORDER_IN_SORTS ifeq ($(strip $(USE_PMODE)),yes) # ICPC 12.0: internal error: backend signals (issue 613286) $(call reduce_optimization,3,0,test_sort,Version_12.0,any,any) $(call reduce_optimization,3,0,test_ksort,Version_12.0,any,any) $(call reduce_optimization,3,0,test_stable_ksort,Version_12.0,any,any) $(call reduce_optimization,3,0,test_bad_cmp,Version_12.0,any,any) $(call reduce_optimization,3,0,sort_file,Version_12.0,any,any) $(call reduce_optimization,3,0,copy_and_sort_file,Version_12.0,any,any) $(call reduce_optimization,3,0,test_parallel_sort,Version_12.0,any,any) $(call reduce_optimization,3,0,test_stable_ksort_all_parameters,Version_12.0,any,any) endif ifeq ($(strip $(USE_MCSTL)),yes) # ICPC 12.0: internal error: backend signals (issue 613286) $(call reduce_optimization,3,0,test_sort,Version_12.0,any,any) $(call reduce_optimization,3,0,test_ksort,Version_12.0,any,any) $(call reduce_optimization,3,0,test_stable_ksort,Version_12.0,any,any) $(call reduce_optimization,3,0,test_bad_cmp,Version_12.0,any,any) $(call reduce_optimization,3,0,sort_file,Version_12.0,any,any) $(call reduce_optimization,3,0,copy_and_sort_file,Version_12.0,any,any) $(call reduce_optimization,3,0,test_parallel_sort,Version_12.0,any,any) $(call reduce_optimization,3,0,test_stable_ksort_all_parameters,Version_12.0,any,any) # ICPC 11.0: internal error: 0_1374 (issue 539748) $(call reduce_optimization,3,0,test_sort,Version_11.0,any,any) $(call reduce_optimization,3,0,test_ksort,Version_11.0,any,any) $(call reduce_optimization,3,0,sort_file,Version_11.0,any,any) $(call reduce_optimization,3,0,test_parallel_sort,Version_11.0,any,any) # ICPC 10.0: internal error: backend signals (issue 466173) $(call reduce_optimization,3,1,async_schedule,Version_10.0,32-bit,any,o) $(call reduce_optimization,3,1,test_scan,Version_10.0,32-bit,any) $(call reduce_optimization,3,1,test_sort,Version_10.0,32-bit,any) $(call reduce_optimization,3,1,test_ksort,Version_10.0,32-bit,any) $(call reduce_optimization,3,1,test_stable_ksort,Version_10.0,32-bit,any) $(call reduce_optimization,3,1,sort_file,Version_10.0,32-bit,any) $(call reduce_optimization,3,1,test_random_shuffle,Version_10.0,32-bit,any) $(call reduce_optimization,3,1,test_parallel_sort,Version_10.0,32-bit,any) endif stxxl-1.3.1/algo/test_sort_all_parameters.h0000644000175000017500000000463211531445437020722 0ustar andreasandreas/*************************************************************************** * algo/test_sort_all_parameters.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2002 Roman Dementiev * Copyright (C) 2008, 2009 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #include #include template struct bulk { char _data[n]; }; template <> struct bulk<0> { }; template struct my_type { typedef KEY key_type; key_type _key; bulk _data; my_type() { } my_type(key_type __key) : _key(__key) { } #ifdef KEY_COMPARE key_type key() const { return _key; } #endif static my_type min_value() { return my_type(std::numeric_limits::min()); } static my_type max_value() { return my_type(std::numeric_limits::max()); } }; template std::ostream & operator << (std::ostream & o, const my_type obj) { #ifndef KEY_COMPARE o << obj._key; #else o << obj.key(); #endif return o; } #ifndef KEY_COMPARE template bool operator < (const my_type & a, const my_type & b) { return a._key < b._key; } template bool operator == (const my_type & a, const my_type & b) { return a._key == b._key; } template bool operator != (const my_type & a, const my_type & b) { return a._key != b._key; } template struct Cmp : public std::less { bool operator () (const T & a, const T & b) const { return a._key < b._key; } static T min_value() { return T::min_value(); } static T max_value() { return T::max_value(); } }; #else template bool operator < (const my_type & a, const my_type & b) { return a.key() < b.key(); } #endif struct zero { unsigned operator () () { return 0; } }; stxxl-1.3.1/algo/test_ksort_all_parameters.cpp0000644000175000017500000001305011271176773021427 0ustar andreasandreas/*************************************************************************** * algo/test_ksort_all_parameters.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2002 Roman Dementiev * Copyright (C) 2008 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ //#define PLAY_WITH_OPT_PREF #include #include #include #include #include #define KEY_COMPARE #include "test_sort_all_parameters.h" #ifndef RECORD_SIZE #define RECORD_SIZE 128 #endif #define MB (1024 * 1024) template void test(stxxl::uint64 data_mem, unsigned memory_to_use) { stxxl::uint64 records_to_sort = data_mem / sizeof(T); typedef stxxl::vector, block_size, alloc_strategy_type> vector_type; memory_to_use = stxxl::div_ceil(memory_to_use, vector_type::block_type::raw_size) * vector_type::block_type::raw_size; vector_type v(records_to_sort); unsigned ndisks = stxxl::config::get_instance()->disks_number(); STXXL_MSG("Sorting " << records_to_sort << " records of size " << sizeof(T)); STXXL_MSG("Total volume " << (records_to_sort * sizeof(T)) / MB << " MiB"); STXXL_MSG("Using " << memory_to_use / MB << " MiB"); STXXL_MSG("Using " << ndisks << " disks"); STXXL_MSG("Using " << alloc_strategy_type::name() << " allocation strategy "); STXXL_MSG("Block size " << vector_type::block_type::raw_size / 1024 << " KiB"); STXXL_MSG("Filling vector..."); stxxl::generate(v.begin(), v.end(), stxxl::random_number32_r(), 32); //std::generate(v.begin(),v.end(),zero()); STXXL_MSG("Sorting vector..."); stxxl::stats_data before(*stxxl::stats::get_instance()); stxxl::ksort(v.begin(), v.end(), memory_to_use); stxxl::stats_data after(*stxxl::stats::get_instance()); STXXL_MSG("Checking order..."); STXXL_MSG((stxxl::is_sorted(v.begin(), v.end()) ? "OK" : "WRONG")); STXXL_MSG("Sorting: " << (after - before)); STXXL_MSG("Total: " << *stxxl::stats::get_instance()); } template void test_all_strategies( stxxl::uint64 data_mem, unsigned memory_to_use, int strategy) { switch (strategy) { case 0: test(data_mem, memory_to_use); break; case 1: test(data_mem, memory_to_use); break; case 2: test(data_mem, memory_to_use); break; case 3: test(data_mem, memory_to_use); break; default: STXXL_ERRMSG("Unknown allocation strategy: " << strategy << ", aborting"); abort(); } } int main(int argc, char * argv[]) { if (argc < 6) { STXXL_ERRMSG("Usage: " << argv[0] << " "); return -1; } #if STXXL_PARALLEL_MULTIWAY_MERGE STXXL_MSG("STXXL_PARALLEL_MULTIWAY_MERGE"); #endif stxxl::uint64 data_mem = stxxl::atoint64(argv[1]) * MB; int sort_mem = atoi(argv[2]) * MB; int strategy = atoi(argv[3]); int block_size = atoi(argv[4]); stxxl::set_seed(strtoul(argv[5], NULL, 10)); STXXL_MSG("Seed " << stxxl::get_next_seed()); stxxl::srandom_number32(); typedef my_type my_default_type; switch (block_size) { case 0: test_all_strategies(data_mem, sort_mem, strategy); break; case 1: test_all_strategies(data_mem, sort_mem, strategy); break; case 2: test_all_strategies(data_mem, sort_mem, strategy); break; case 3: test_all_strategies(data_mem, sort_mem, strategy); break; case 4: test_all_strategies(data_mem, sort_mem, strategy); break; case 5: test_all_strategies(data_mem, sort_mem, strategy); break; case 6: test_all_strategies(data_mem, sort_mem, strategy); break; case 7: test_all_strategies(data_mem, sort_mem, strategy); break; case 8: test_all_strategies(data_mem, sort_mem, strategy); break; case 9: test_all_strategies(data_mem, sort_mem, strategy); break; case 10: test_all_strategies(data_mem, sort_mem, strategy); break; case 11: test_all_strategies, 2 * MB>(data_mem, sort_mem, strategy); break; case 12: test_all_strategies, 2 * MB + 4096>(data_mem, sort_mem, strategy); break; case 13: test_all_strategies, 2 * MB + 4096>(data_mem, sort_mem, strategy); break; case 14: test_all_strategies, 2 * MB>(data_mem, sort_mem, strategy); break; default: STXXL_ERRMSG("Unknown block size: " << block_size << ", aborting"); abort(); } return 0; } stxxl-1.3.1/algo/test_asch.cpp0000644000175000017500000000375511535151017016126 0ustar andreasandreas/*************************************************************************** * algo/test_asch.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2002 Roman Dementiev * Copyright (C) 2009 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #include #include #include #include // Test async schedule algorithm int main(int argc, char * argv[]) { if (argc < 5) { STXXL_ERRMSG("Usage: " << argv[0] << " D L m seed"); return -1; } int i; const stxxl::int_type D = atoi(argv[1]); const stxxl::int_type L = atoi(argv[2]); const stxxl::int_type m = atoi(argv[3]); stxxl::ran32State = atoi(argv[4]); stxxl::int_type * disks = new stxxl::int_type[L]; stxxl::int_type * prefetch_order = new stxxl::int_type[L]; int * count = new int[D]; for (i = 0; i < D; i++) count[i] = 0; stxxl::random_number<> rnd; for (i = 0; i < L; i++) { disks[i] = rnd(D); count[disks[i]]++; } for (i = 0; i < D; i++) std::cout << "Disk " << i << " has " << count[i] << " blocks" << std::endl; stxxl::compute_prefetch_schedule(disks, disks + L, prefetch_order, m, D); STXXL_MSG("Prefetch order:"); for (i = 0; i < L; ++i) { STXXL_MSG("request " << prefetch_order[i] << " on disk " << disks[prefetch_order[i]]); } STXXL_MSG("Request order:"); for (i = 0; i < L; ++i) { int j; for (j = 0; prefetch_order[j] != i; ++j) ; STXXL_MSG("request " << i << " on disk " << disks[i] << " scheduled as " << j); } delete[] count; delete[] disks; delete[] prefetch_order; } // vim: et:ts=4:sw=4 stxxl-1.3.1/algo/Makefile.common0000644000175000017500000000046511536140476016377 0ustar andreasandreasTESTS = test_scan test_sort test_ksort test_stable_ksort sort_file copy_and_sort_file test_random_shuffle test_asch test_bad_cmp TESTS_LONG_COMPILE = test_sort_all_parameters test_ksort_all_parameters test_stable_ksort_all_parameters TESTS_NON_MSVC = test_parallel_sort LIB_SRC = async_schedule.cpp stxxl-1.3.1/algo/test_scan.cpp0000644000175000017500000000515311042046537016131 0ustar andreasandreas/*************************************************************************** * algo/test_scan.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2002 Roman Dementiev * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ //! \example algo/test_scan.cpp //! This is an example of how to use \c stxxl::for_each() and \c stxxl::find() algorithms #include #include #include #include using stxxl::int64; using stxxl::timestamp; template struct counter { type value; counter(type v = type(0)) : value(v) { } type operator () () { type old_val = value; value++; return old_val; } }; template struct square { void operator () (type & arg) { arg = arg * arg; } }; template struct fill_value { type val; fill_value(const type & v_) : val(v_) { } type operator () () { return val; } }; int main() { stxxl::vector::size_type i; stxxl::vector v(64 * int64(1024 * 1024)); double b, e; STXXL_MSG("write " << (v.end() - v.begin()) << " elements ..."); stxxl::generate(v.begin(), v.end(), counter(), 4); STXXL_MSG("for_each_m ..."); b = timestamp(); stxxl::for_each_m(v.begin(), v.end(), square(), 4); e = timestamp(); STXXL_MSG("for_each_m time: " << (e - b)); STXXL_MSG("check"); for (i = 0; i < v.size(); ++i) { if (v[i] != int64(i * i)) STXXL_MSG("Error at position " << i); } STXXL_MSG("Pos of value 1023: " << (stxxl::find(v.begin(), v.end(), 1023, 4) - v.begin())); STXXL_MSG("Pos of value 1048576: " << (stxxl::find(v.begin(), v.end(), 1024 * 1024, 4) - v.begin())); STXXL_MSG("Pos of value 1024: " << (stxxl::find(v.begin(), v.end(), 32 * 32, 4) - v.begin())); STXXL_MSG("generate ..."); b = timestamp(); stxxl::generate(v.begin() + 1, v.end() - 1, fill_value(555), 4); e = timestamp(); STXXL_MSG("generate: " << (e - b)); STXXL_MSG("check"); if (v[0] != 0) STXXL_MSG("Error at position " << i); if (v[v.size() - 1] != int64((v.size() - 1) * (v.size() - 1))) STXXL_MSG("Error at position " << i); for (i = 1; i < v.size() - 1; ++i) { if (v[i] != 555) STXXL_MSG("Error at position " << i); } return 0; } stxxl-1.3.1/algo/test_bad_cmp.cpp0000644000175000017500000001160411536140476016575 0ustar andreasandreas/*************************************************************************** * algo/test_bad_cmp.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2002 Roman Dementiev * Copyright (C) 2011 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ //! \example algo/test_bad_cmp.cpp //! This is an example of how NOT to use \c stxxl::sort() algorithm. //! Here min_value and max_value are used as keys which is forbidden. #include #include #include struct my_type { typedef unsigned key_type; key_type _key; key_type _data; key_type key() const { return _key; } my_type() { } my_type(key_type __key) : _key(__key), _data(0) { } static my_type min_value() { return my_type((std::numeric_limits::min)()); } static my_type max_value() { return my_type((std::numeric_limits::max)()); } ~my_type() { } }; std::ostream & operator << (std::ostream & o, const my_type & obj) { o << obj._key; return o; } bool operator < (const my_type & a, const my_type & b) { return a.key() < b.key(); } bool operator == (const my_type & a, const my_type & b) { return a.key() == b.key(); } bool operator != (const my_type & a, const my_type & b) { return a.key() != b.key(); } struct cmp : public std::less { my_type min_value() const { return my_type::min_value(); } my_type max_value() const { return my_type::max_value(); } }; int main() { #if STXXL_PARALLEL_MULTIWAY_MERGE STXXL_MSG("STXXL_PARALLEL_MULTIWAY_MERGE"); #endif unsigned memory_to_use = 128 * 1024 * 1024; typedef stxxl::vector vector_type; const stxxl::int64 n_records = stxxl::int64(384) * stxxl::int64(1024 * 1024) / sizeof(my_type); vector_type v(n_records); stxxl::int64 aliens, not_stable; int bs = vector_type::block_type::size; STXXL_MSG("Filling vector with min_value..., input size = " << v.size() << " elements (" << ((v.size() * sizeof(my_type)) >> 20) << " MiB)"); for (vector_type::size_type i = 0; i < v.size(); i++) { v[i]._key = 0; v[i]._data = i + 1; } STXXL_MSG("Checking order..."); STXXL_MSG(((stxxl::is_sorted(v.begin(), v.end(), cmp())) ? "OK" : "WRONG")); STXXL_MSG("Sorting (using " << (memory_to_use >> 20) << " MiB of memory)..."); stxxl::sort(v.begin(), v.end(), cmp(), memory_to_use); STXXL_MSG("Checking order..."); STXXL_MSG(((stxxl::is_sorted(v.begin(), v.end(), cmp())) ? "OK" : "WRONG")); aliens = not_stable = 0; for (vector_type::size_type i = 0; i < v.size(); i++) { if (v[i]._data < 1) ++aliens; else if (v[i]._data != i + 1) ++not_stable; v[i]._data = i + 1; } STXXL_MSG("elements that were not in the input: " << aliens); STXXL_MSG("elements not on their expected location: " << not_stable); STXXL_MSG("Sorting subset (using " << (memory_to_use >> 20) << " MiB of memory)..."); stxxl::sort(v.begin() + bs - 1, v.end() - bs + 2, cmp(), memory_to_use); STXXL_MSG("Checking order..."); STXXL_MSG(((stxxl::is_sorted(v.begin(), v.end(), cmp())) ? "OK" : "WRONG")); aliens = not_stable = 0; for (vector_type::size_type i = 0; i < v.size(); i++) { if (v[i]._data < 1) ++aliens; else if (v[i]._data != i + 1) ++not_stable; v[i]._data = i + 1; } STXXL_MSG("elements that were not in the input: " << aliens); STXXL_MSG("elements not on their expected location: " << not_stable); STXXL_MSG("Filling vector with max_value..., input size = " << v.size() << " elements (" << ((v.size() * sizeof(my_type)) >> 20) << " MiB)"); for (vector_type::size_type i = 0; i < v.size(); i++) { v[i]._key = unsigned(-1); v[i]._data = i + 1; } STXXL_MSG("Sorting subset (using " << (memory_to_use >> 20) << " MiB of memory)..."); stxxl::sort(v.begin() + bs - 1, v.end() - bs + 2, cmp(), memory_to_use); STXXL_MSG("Checking order..."); STXXL_MSG(((stxxl::is_sorted(v.begin(), v.end(), cmp())) ? "OK" : "WRONG")); aliens = not_stable = 0; for (vector_type::size_type i = 0; i < v.size(); i++) { if (v[i]._data < 1) ++aliens; else if (v[i]._data != i + 1) ++not_stable; v[i]._data = i + 1; } STXXL_MSG("elements that were not in the input: " << aliens); STXXL_MSG("elements not on their expected location: " << not_stable); STXXL_MSG("Done, output size=" << v.size() << " block size=" << bs); return 0; } // vim: et:ts=4:sw=4 stxxl-1.3.1/algo/sort_file.cpp0000644000175000017500000001100611336266304016130 0ustar andreasandreas/*************************************************************************** * algo/sort_file.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2002-2003 Roman Dementiev * Copyright (C) 2009 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ //! \example algo/sort_file.cpp //! This example imports a file into an \c stxxl::vector without copying its //! content and then sorts it using stxxl::sort / stxxl::ksort / ... #include #include #include #include #include #include struct my_type { typedef unsigned key_type; key_type _key; char _data[128 - sizeof(key_type)]; key_type key() const { return _key; } my_type() { } my_type(key_type __key) : _key(__key) { } static my_type min_value() { return my_type((std::numeric_limits::min)()); } static my_type max_value() { return my_type((std::numeric_limits::max)()); } }; inline bool operator < (const my_type & a, const my_type & b) { return a.key() < b.key(); } inline bool operator == (const my_type & a, const my_type & b) { return a.key() == b.key(); } struct Cmp { typedef my_type first_argument_type; typedef my_type second_argument_type; typedef bool result_type; bool operator () (const my_type & a, const my_type & b) const { return a < b; } static my_type min_value() { return my_type::min_value(); } static my_type max_value() { return my_type::max_value(); } }; std::ostream & operator << (std::ostream & o, const my_type & obj) { o << obj._key; return o; } int main(int argc, char ** argv) { if (argc < 3) { std::cout << "Usage: " << argv[0] << " action file" << std::endl; std::cout << " where action is one of generate, sort, ksort, stable_sort, stable_ksort" << std::endl; return -1; } const unsigned int block_size = sizeof(my_type) * 4096; if (strcmp(argv[1], "generate") == 0) { const my_type::key_type num_elements = 1 * 1024 * 1024; const unsigned int records_in_block = block_size / sizeof(my_type); stxxl::syscall_file f(argv[2], stxxl::file::CREAT | stxxl::file::RDWR); my_type * array = (my_type *)stxxl::aligned_alloc(block_size); memset(array, 0, block_size); my_type::key_type cur_key = num_elements; for (unsigned i = 0; i < num_elements / records_in_block; i++) { for (unsigned j = 0; j < records_in_block; j++) array[j]._key = cur_key--; stxxl::request_ptr req = f.awrite((void *)array, stxxl::int64(i) * block_size, block_size, stxxl::default_completion_handler()); req->wait(); } stxxl::aligned_dealloc(array); } else { #if STXXL_PARALLEL_MULTIWAY_MERGE STXXL_MSG("STXXL_PARALLEL_MULTIWAY_MERGE"); #endif stxxl::syscall_file f(argv[2], stxxl::file::DIRECT | stxxl::file::RDWR); unsigned memory_to_use = 50 * 1024 * 1024; typedef stxxl::vector, block_size> vector_type; vector_type v(&f); /* STXXL_MSG("Printing..."); for(stxxl::int64 i=0; i < v.size(); i++) STXXL_MSG(v[i].key()); */ STXXL_MSG("Checking order..."); STXXL_MSG((stxxl::is_sorted(v.begin(), v.end()) ? "OK" : "WRONG")); STXXL_MSG("Sorting..."); if (strcmp(argv[1], "sort") == 0) { stxxl::sort(v.begin(), v.end(), Cmp(), memory_to_use); #if 0 // stable_sort is not yet implemented } else if (strcmp(argv[1], "stable_sort") == 0) { stxxl::stable_sort(v.begin(), v.end(), memory_to_use); #endif } else if (strcmp(argv[1], "ksort") == 0) { stxxl::ksort(v.begin(), v.end(), memory_to_use); } else if (strcmp(argv[1], "stable_ksort") == 0) { stxxl::stable_ksort(v.begin(), v.end(), memory_to_use); } else { STXXL_MSG("Not implemented: " << argv[1]); } STXXL_MSG("Checking order..."); STXXL_MSG((stxxl::is_sorted(v.begin(), v.end()) ? "OK" : "WRONG")); } return 0; } // vim: et:ts=4:sw=4 stxxl-1.3.1/algo/test_sort.cpp0000644000175000017500000000645111535151017016173 0ustar andreasandreas/*************************************************************************** * algo/test_sort.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2002 Roman Dementiev * Copyright (C) 2010 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ //! \example algo/test_sort.cpp //! This is an example of how to use \c stxxl::sort() algorithm #include #include #include #define RECORD_SIZE 8 struct my_type { typedef unsigned key_type; key_type _key; char _data[RECORD_SIZE - sizeof(key_type)]; key_type key() const { return _key; } my_type() { } my_type(key_type __key) : _key(__key) { } static my_type min_value() { return my_type((std::numeric_limits::min)()); } static my_type max_value() { return my_type((std::numeric_limits::max)()); } ~my_type() { } }; std::ostream & operator << (std::ostream & o, const my_type & obj) { o << obj._key; return o; } bool operator < (const my_type & a, const my_type & b) { return a.key() < b.key(); } bool operator == (const my_type & a, const my_type & b) { return a.key() == b.key(); } bool operator != (const my_type & a, const my_type & b) { return a.key() != b.key(); } struct cmp : public std::less { my_type min_value() const { return my_type::min_value(); } my_type max_value() const { return my_type::max_value(); } }; int main() { #if STXXL_PARALLEL_MULTIWAY_MERGE STXXL_MSG("STXXL_PARALLEL_MULTIWAY_MERGE"); #endif unsigned memory_to_use = 128 * 1024 * 1024; typedef stxxl::vector vector_type; { // test small vector that can be sorted internally vector_type v(3); v[0] = 42; v[1] = 0; v[2] = 23; STXXL_MSG("small vector unsorted " << v[0] << " " << v[1] << " " << v[2]); //stxxl::sort(v.begin(), v.end(), cmp(), memory_to_use); stxxl::stl_in_memory_sort(v.begin(), v.end(), cmp()); STXXL_MSG("small vector sorted " << v[0] << " " << v[1] << " " << v[2]); assert(stxxl::is_sorted(v.begin(), v.end(), cmp())); } const stxxl::int64 n_records = stxxl::int64(384) * stxxl::int64(1024 * 1024) / sizeof(my_type); vector_type v(n_records); stxxl::random_number32 rnd; STXXL_MSG("Filling vector..., input size = " << v.size() << " elements (" << ((v.size() * sizeof(my_type)) >> 20) << " MiB)"); for (vector_type::size_type i = 0; i < v.size(); i++) v[i]._key = 1 + (rnd() % 0xfffffff); STXXL_MSG("Checking order..."); STXXL_MSG(((stxxl::is_sorted(v.begin(), v.end(), cmp())) ? "OK" : "WRONG")); STXXL_MSG("Sorting (using " << (memory_to_use >> 20) << " MiB of memory)..."); stxxl::sort(v.begin(), v.end(), cmp(), memory_to_use); STXXL_MSG("Checking order..."); STXXL_MSG(((stxxl::is_sorted(v.begin(), v.end(), cmp())) ? "OK" : "WRONG")); STXXL_MSG("Done, output size=" << v.size()); return 0; } // vim: et:ts=4:sw=4 stxxl-1.3.1/algo/async_schedule.cpp0000644000175000017500000001471511535151017017140 0ustar andreasandreas/*************************************************************************** * algo/async_schedule.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2002, 2009 Roman Dementiev * Copyright (C) 2009, 2010 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ // Implements the "prudent prefetching" as described in // D. Hutchinson, P. Sanders, J. S. Vitter: Duality between prefetching // and queued writing on parallel disks, 2005 // DOI: 10.1137/S0097539703431573 #include #include #include #include #include #include #include #include __STXXL_BEGIN_NAMESPACE namespace async_schedule_local { struct sim_event // only one type of event: WRITE COMPLETED { int_type timestamp; int_type iblock; inline sim_event(int_type t, int_type b) : timestamp(t), iblock(b) { } }; struct sim_event_cmp : public std::binary_function { inline bool operator () (const sim_event & a, const sim_event & b) const { return a.timestamp > b.timestamp; } }; typedef std::pair write_time_pair; struct write_time_cmp : public std::binary_function { inline bool operator () (const write_time_pair & a, const write_time_pair & b) const { return a.second > b.second; } }; static inline int_type get_disk(int_type i, const int_type * disks, int_type D) { int_type disk = disks[i]; if (disk == file::NO_ALLOCATOR) disk = D; // remap to sentinel assert(0 <= disk && disk <= D); return disk; } int_type simulate_async_write( const int_type * disks, const int_type L, const int_type m_init, const int_type D, std::pair * o_time) { typedef std::priority_queue, sim_event_cmp> event_queue_type; typedef std::queue disk_queue_type; assert(L >= D); disk_queue_type * disk_queues = new disk_queue_type[D + 1]; // + sentinel for remapping NO_ALLOCATOR event_queue_type event_queue; int_type m = m_init; int_type i = L - 1; int_type oldtime = 0; bool * disk_busy = new bool[D + 1]; while (m && (i >= 0)) { int_type disk = get_disk(i, disks, D); disk_queues[disk].push(i); i--; m--; } for (int_type ii = 0; ii <= D; ii++) if (!disk_queues[ii].empty()) { int_type j = disk_queues[ii].front(); disk_queues[ii].pop(); event_queue.push(sim_event(1, j)); //STXXL_MSG("Block "<(cur.iblock, cur.timestamp); if (i >= 0) { int_type disk = get_disk(i, disks, D); if (disk_busy[disk]) { disk_queues[disk].push(i--); } else { if (!disk_queues[disk].empty()) { STXXL_VERBOSE1("c Block " << disk_queues[disk].front() << " scheduled for time " << cur.timestamp + 1); event_queue.push(sim_event(cur.timestamp + 1, disk_queues[disk].front())); disk_queues[disk].pop(); } else { STXXL_VERBOSE1("a Block " << i << " scheduled for time " << cur.timestamp + 1); event_queue.push(sim_event(cur.timestamp + 1, i--)); } disk_busy[disk] = true; } } // add next block to write int_type disk = get_disk(cur.iblock, disks, D); if (!disk_busy[disk] && !disk_queues[disk].empty()) { STXXL_VERBOSE1("b Block " << disk_queues[disk].front() << " scheduled for time " << cur.timestamp + 1); event_queue.push(sim_event(cur.timestamp + 1, disk_queues[disk].front())); disk_queues[disk].pop(); disk_busy[disk] = true; } } assert(i == -1); for (int_type i = 0; i <= D; i++) assert(disk_queues[i].empty()); delete[] disk_busy; delete[] disk_queues; return (oldtime - 1); } } // namespace async_schedule_local void compute_prefetch_schedule( const int_type * first, const int_type * last, int_type * out_first, int_type m, int_type D) { typedef std::pair pair_type; int_type L = last - first; if (L <= D) { for (int_type i = 0; i < L; ++i) out_first[i] = i; return; } pair_type * write_order = new pair_type[L]; int_type w_steps = async_schedule_local::simulate_async_write(first, L, m, D, write_order); STXXL_VERBOSE1("Write steps: " << w_steps); for (int_type i = 0; i < L; i++) STXXL_VERBOSE1(first[i] << " " << write_order[i].first << " " << write_order[i].second); std::stable_sort(write_order, write_order + L, async_schedule_local::write_time_cmp() _STXXL_FORCE_SEQUENTIAL); for (int_type i = 0; i < L; i++) { out_first[i] = write_order[i].first; //if(out_first[i] != i) STXXL_VERBOSE1(i << " " << out_first[i]); } delete[] write_order; STXXL_UNUSED(w_steps); } __STXXL_END_NAMESPACE // vim: et:ts=4:sw=4 stxxl-1.3.1/algo/test_random_shuffle.cpp0000644000175000017500000000537311253216271020203 0ustar andreasandreas/*************************************************************************** * algo/test_random_shuffle.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2007 Manuel Krings * Copyright (C) 2007 Markus Westphal * Copyright (C) 2009 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ // TODO: test both vector and non-vector variant of random_shuffle // TODO: test recursion, improve verboseness //! \example algo/test_random_shuffle.cpp //! Test \c stxxl::random_shuffle() #include #include template struct counter { type value; counter(type v = type(0)) : value(v) { } type operator () () { type old_val = value; value++; return old_val; } }; void long_test() { typedef stxxl::vector ext_vec_type; ext_vec_type STXXLVector(1024 * 1024 * 256 / sizeof(int)); STXXL_MSG("Filling vector with increasing values..."); stxxl::generate(STXXLVector.begin(), STXXLVector.end(), counter(), 4); stxxl::uint64 i; STXXL_MSG("Begin: "); for (i = 0; i < 10; i++) STXXL_MSG(STXXLVector[i]); STXXL_MSG("End: "); for (i = STXXLVector.size() - 10; i < STXXLVector.size(); i++) STXXL_MSG(STXXLVector[i]); STXXL_MSG("Permute randomly..."); stxxl::random_shuffle(STXXLVector.begin(), STXXLVector.end(), 1024 * 1024 * 128); STXXL_MSG("Begin: "); for (i = 0; i < 10; i++) STXXL_MSG(STXXLVector[i]); STXXL_MSG("End: "); for (i = STXXLVector.size() - 10; i < STXXLVector.size(); i++) STXXL_MSG(STXXLVector[i]); } void short_test() { STXXL_STATIC_ASSERT(sizeof(int) == 4); typedef stxxl::VECTOR_GENERATOR::result vector_type; vector_type::size_type i; vector_type v(2048); for (i = 0; i < v.size(); ++i) v[i] = i / 1024 + 1; std::cout << v.size() << std::endl; std::cout << "before shuffle:" << std::endl; for (i = 0; i < v.size(); ++i) { std::cout << v[i] << " "; if ((i & 511) == 511) std::cout << std::endl; } std::cout << std::endl; v.flush(); stxxl::random_shuffle(v.begin() + 512, v.begin() + 512 + 1024, 64 * 1024); std::cout << "after shuffle:" << std::endl; for (i = 0; i < v.size(); ++i) { std::cout << v[i] << " "; if ((i & 511) == 511) std::cout << std::endl; } std::cout << std::endl; } int main() { short_test(); long_test(); } // vim: et:ts=4:sw=4 stxxl-1.3.1/algo/test_stable_ksort.cpp0000644000175000017500000000403711531237734017705 0ustar andreasandreas/*************************************************************************** * algo/test_stable_ksort.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2003, 2008 Roman Dementiev * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ //! \example algo/test_stable_ksort.cpp //! This is an example of how to use \c stxxl::ksort() algorithm #include #include #include #include struct my_type { typedef unsigned key_type; key_type _key; char _data[128 - sizeof(key_type)]; key_type key() const { return _key; } my_type() { } my_type(key_type __key) : _key(__key) { } static my_type min_value() { return my_type((std::numeric_limits::min)()); } static my_type max_value() { return my_type((std::numeric_limits::max)()); } }; bool operator < (const my_type & a, const my_type & b) { return a.key() < b.key(); } int main() { #if STXXL_PARALLEL_MULTIWAY_MERGE STXXL_MSG("STXXL_PARALLEL_MULTIWAY_MERGE"); #endif unsigned memory_to_use = 44 * 1024 * 1024; typedef stxxl::vector vector_type; const stxxl::int64 n_records = 2 * 32 * stxxl::int64(1024 * 1024) / sizeof(my_type); vector_type v(n_records); stxxl::random_number32 rnd; STXXL_MSG("Filling vector... " << rnd() << " " << rnd() << " " << rnd()); for (vector_type::size_type i = 0; i < v.size(); i++) v[i]._key = (rnd() / 2) * 2; STXXL_MSG("Checking order..."); STXXL_MSG(((stxxl::is_sorted(v.begin(), v.end())) ? "OK" : "WRONG")); STXXL_MSG("Sorting..."); stxxl::stable_ksort(v.begin(), v.end(), memory_to_use); STXXL_MSG("Checking order..."); STXXL_MSG(((stxxl::is_sorted(v.begin(), v.end())) ? "OK" : "WRONG")); return 0; } stxxl-1.3.1/algo/Makefile0000644000175000017500000000766111536140476015115 0ustar andreasandreasinclude Makefile.common include ../make.settings tests: $(TESTS) #tests: $(TESTS_LONG_COMPILE) #tests: $(TESTS_NON_MSVC) lib: async_schedule.$(OBJEXT) async_schedule.$(OBJEXT): async_schedule.cpp $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c async_schedule.cpp DEPENDENCIES = $(COMMON_FILES) $(IO_LAYER_FILES) $(MNG_LAYER_FILES) $(CONTAINER_FILES) $(ALGO_FILES) test_sort: test_sort.$(EXEEXT) test_sort.$(EXEEXT): test_sort.cpp $(DEPENDENCIES) $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c test_sort.cpp -DSTXXL_VERBOSE_LEVEL=0 $(LINKER) test_sort.$(OBJEXT) $(OUT)test_sort.$(EXEEXT) $(STXXL_LINKER_OPTIONS) test_sort_all_parameters: test_sort_all_parameters.$(EXEEXT) test_sort_all_parameters.$(EXEEXT): test_sort_all_parameters.cpp # takes long to compile $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c test_sort_all_parameters.cpp $(LINKER) test_sort_all_parameters.$(OBJEXT) $(OUT)test_sort_all_parameters.$(EXEEXT) $(STXXL_LINKER_OPTIONS) test_ksort: test_ksort.$(EXEEXT) test_ksort.$(EXEEXT): test_ksort.cpp $(DEPENDENCIES) $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c test_ksort.cpp -DSTXXL_CHECK_ORDER_IN_SORTS $(LINKER) test_ksort.$(OBJEXT) $(OUT)test_ksort.$(EXEEXT) $(STXXL_LINKER_OPTIONS) test_ksort_all_parameters: test_ksort_all_parameters.$(EXEEXT) test_ksort_all_parameters.$(EXEEXT): test_ksort_all_parameters.cpp $(DEPENDENCIES) # takes long to compile $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c test_ksort_all_parameters.cpp $(LINKER) test_ksort_all_parameters.$(OBJEXT) $(OUT)test_ksort_all_parameters.$(EXEEXT) $(STXXL_LINKER_OPTIONS) test_stable_ksort: test_stable_ksort.$(EXEEXT) test_stable_ksort.$(EXEEXT): test_stable_ksort.cpp $(DEPENDENCIES) $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c test_stable_ksort.cpp $(LINKER) test_stable_ksort.$(OBJEXT) $(OUT)test_stable_ksort.$(EXEEXT) $(STXXL_LINKER_OPTIONS) test_stable_ksort_all_parameters: test_stable_ksort_all_parameters.$(EXEEXT) test_stable_ksort_all_parameters.$(EXEEXT): test_stable_ksort_all_parameters.cpp $(DEPENDENCIES) # takes long to compile $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c test_stable_ksort_all_parameters.cpp $(LINKER) test_stable_ksort_all_parameters.$(OBJEXT) $(OUT)test_stable_ksort_all_parameters.$(EXEEXT) $(STXXL_LINKER_OPTIONS) sort_file: sort_file.$(EXEEXT) sort_file.$(EXEEXT): sort_file.cpp $(DEPENDENCIES) $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c sort_file.cpp $(LINKER) sort_file.$(OBJEXT) $(OUT)sort_file.$(EXEEXT) $(STXXL_LINKER_OPTIONS) copy_and_sort_file: copy_and_sort_file.$(EXEEXT) copy_and_sort_file.$(EXEEXT): copy_and_sort_file.cpp $(DEPENDENCIES) $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c copy_and_sort_file.cpp $(LINKER) copy_and_sort_file.$(OBJEXT) $(OUT)copy_and_sort_file.$(EXEEXT) $(STXXL_LINKER_OPTIONS) test_asch: test_asch.$(EXEEXT) test_asch.$(EXEEXT): test_asch.cpp $(DEPENDENCIES) $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c test_asch.cpp $(LINKER) test_asch.$(OBJEXT) $(OUT)test_asch.$(EXEEXT) $(STXXL_LINKER_OPTIONS) test_scan: test_scan.$(EXEEXT) test_scan.$(EXEEXT): test_scan.cpp $(DEPENDENCIES) $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c test_scan.cpp $(LINKER) test_scan.$(OBJEXT) $(OUT)test_scan.$(EXEEXT) $(STXXL_LINKER_OPTIONS) gen_file: gen_file.$(EXEEXT) gen_file.$(EXEEXT): gen_file.cpp $(DEPENDENCIES) $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c gen_file.cpp $(LINKER) gen_file.$(OBJEXT) $(OUT)gen_file.$(EXEEXT) $(STXXL_LINKER_OPTIONS) test_random_shuffle: test_random_shuffle.$(EXEEXT) test_random_shuffle.$(EXEEXT): test_random_shuffle.cpp $(DEPENDENCIES) $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c test_random_shuffle.cpp -DSTXXL_VERBOSE_LEVEL=0 $(LINKER) test_random_shuffle.$(OBJEXT) $(OUT)test_random_shuffle.$(EXEEXT) $(STXXL_LINKER_OPTIONS) test_bad_cmp: test_bad_cmp.$(EXEEXT) test_bad_cmp.$(EXEEXT): test_bad_cmp.cpp $(DEPENDENCIES) $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c test_bad_cmp.cpp -DSTXXL_VERBOSE_LEVEL=0 $(LINKER) test_bad_cmp.$(OBJEXT) $(OUT)test_bad_cmp.$(EXEEXT) $(STXXL_LINKER_OPTIONS) clean: $(RM) $(CLEAN_TARGETS) stxxl-1.3.1/include/0000755000175000017500000000000011536252421014136 5ustar andreasandreasstxxl-1.3.1/include/bits/0000755000175000017500000000000011536252421015077 5ustar andreasandreasstxxl-1.3.1/include/bits/intel_compatibility.h0000644000175000017500000000307611261056513021321 0ustar andreasandreas#ifndef STXXL_MCSTL_INTEL_COMPATIBILITY_HEADER_INCLUDED #define STXXL_MCSTL_INTEL_COMPATIBILITY_HEADER_INCLUDED /*************************************************************************** * Copyright (C) 2007 by Johannes Singler * * Copyright (C) 2008 by Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * * (See accompanying file LICENSE_1_0.txt or copy at * * http://www.boost.org/LICENSE_1_0.txt) * * Part of the STXXL and MCSTL. * ***************************************************************************/ /** @file intel_compatibility.h * @brief Intel compiler compatibility work-around. */ #if defined(__ICC) && (__ICC < 1100) /** @brief Fake function that will cause linking failure if used. */ template T1 __in_icc_there_is_no__sync_fetch_and_add(T1 *, T2); #if 0 // replacing the overloaded builtin function 'T __sync_fetch_and_add(T*, T)' // with 'int32 _InterlockedExchangeAdd(int32, int32)' is not a good idea #define __sync_fetch_and_add(ptr,addend) _InterlockedExchangeAdd(const_cast(reinterpret_cast(ptr)), addend) #endif /** @brief Replacement of unknown atomic builtin function. * Should work as long as it isn't instantiated. */ #undef __sync_fetch_and_add #define __sync_fetch_and_add __in_icc_there_is_no__sync_fetch_and_add #endif #endif // !STXXL_MCSTL_INTEL_COMPATIBILITY_HEADER_INCLUDED stxxl-1.3.1/include/stxxl/0000755000175000017500000000000011536252421015320 5ustar andreasandreasstxxl-1.3.1/include/stxxl/timer0000644000175000017500000000077211026753412016371 0ustar andreasandreas/*************************************************************************** * include/stxxl/timer * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2007 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #include stxxl-1.3.1/include/stxxl/random0000644000175000017500000000077211026753412016531 0ustar andreasandreas/*************************************************************************** * include/stxxl/random * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2007 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #include stxxl-1.3.1/include/stxxl/mng0000644000175000017500000000111711260736261016027 0ustar andreasandreas/*************************************************************************** * include/stxxl/mng * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2007, 2009 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #include #include #include stxxl-1.3.1/include/stxxl/queue0000644000175000017500000000077611026753412016401 0ustar andreasandreas/*************************************************************************** * include/stxxl/queue * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2007 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #include stxxl-1.3.1/include/stxxl/scan0000644000175000017500000000076611026753412016200 0ustar andreasandreas/*************************************************************************** * include/stxxl/scan * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2007 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #include stxxl-1.3.1/include/stxxl/priority_queue0000644000175000017500000000102011026753412020321 0ustar andreasandreas/*************************************************************************** * include/stxxl/priority_queue * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2007 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #include stxxl-1.3.1/include/stxxl/algorithm0000644000175000017500000000115211032446675017237 0ustar andreasandreas/*************************************************************************** * include/stxxl/algorithm * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2007 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #include #include #include //#include #include stxxl-1.3.1/include/stxxl/mallocstats0000644000175000017500000000100011026753412017560 0ustar andreasandreas/*************************************************************************** * include/stxxl/mallocstats * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2007 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #include stxxl-1.3.1/include/stxxl/sort0000644000175000017500000000076611026753412016243 0ustar andreasandreas/*************************************************************************** * include/stxxl/sort * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2007 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #include stxxl-1.3.1/include/stxxl/request0000644000175000017500000000112411535500414016726 0ustar andreasandreas/*************************************************************************** * include/stxxl/request * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2011 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #include #include #include stxxl-1.3.1/include/stxxl/stream0000644000175000017500000000104711026753412016540 0ustar andreasandreas/*************************************************************************** * include/stxxl/stream * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2007 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #include #include stxxl-1.3.1/include/stxxl/stable_ksort0000644000175000017500000000100611026753412017734 0ustar andreasandreas/*************************************************************************** * include/stxxl/stable_ksort * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2007 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #include stxxl-1.3.1/include/stxxl/random_shuffle0000644000175000017500000000101711050102230020215 0ustar andreasandreas/*************************************************************************** * include/stxxl/random_shuffle * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2008 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #include stxxl-1.3.1/include/stxxl/stats0000644000175000017500000000077511513567471016423 0ustar andreasandreas/*************************************************************************** * include/stxxl/stats * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2011 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #include stxxl-1.3.1/include/stxxl/bits/0000755000175000017500000000000011536252421016261 5ustar andreasandreasstxxl-1.3.1/include/stxxl/bits/mng/0000755000175000017500000000000011536252421017042 5ustar andreasandreasstxxl-1.3.1/include/stxxl/bits/mng/prefetch_pool.h0000644000175000017500000002403511535151017022046 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/mng/prefetch_pool.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2003-2004 Roman Dementiev * Copyright (C) 2009 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_PREFETCH_POOL_HEADER #define STXXL_PREFETCH_POOL_HEADER #include #ifdef STXXL_BOOST_CONFIG #include #endif #include #include __STXXL_BEGIN_NAMESPACE //! \addtogroup schedlayer //! \{ //! \brief Implements dynamically resizable prefetching pool template class prefetch_pool : private noncopyable { public: typedef BlockType block_type; typedef typename block_type::bid_type bid_type; protected: struct bid_hash { size_t operator () (const bid_type & bid) const { size_t result = size_t(bid.storage) + size_t(bid.offset & 0xffffffff) + size_t(bid.offset >> 32); return result; } #ifdef BOOST_MSVC bool operator () (const bid_type & a, const bid_type & b) const { return (a.storage < b.storage) || (a.storage == b.storage && a.offset < b.offset); } enum { // parameters for hash table bucket_size = 4, // 0 < bucket_size min_buckets = 8 // min_buckets = 2 ^^ N, 0 < N }; #endif }; typedef std::pair busy_entry; typedef typename compat_hash_map::result hash_map_type; typedef typename std::list::iterator free_blocks_iterator; typedef typename hash_map_type::iterator busy_blocks_iterator; // contains free prefetch blocks std::list free_blocks; // blocks that are in reading or already read but not retrieved by user hash_map_type busy_blocks; unsigned_type free_blocks_size; public: //! \brief Constructs pool //! \param init_size initial number of blocks in the pool explicit prefetch_pool(unsigned_type init_size = 1) : free_blocks_size(init_size) { unsigned_type i = 0; for ( ; i < init_size; ++i) free_blocks.push_back(new block_type); } void swap(prefetch_pool & obj) { std::swap(free_blocks, obj.free_blocks); std::swap(busy_blocks, obj.busy_blocks); std::swap(free_blocks_size, obj.free_blocks_size); } //! \brief Waits for completion of all ongoing read requests and frees memory virtual ~prefetch_pool() { while (!free_blocks.empty()) { delete free_blocks.back(); free_blocks.pop_back(); } try { busy_blocks_iterator i2 = busy_blocks.begin(); for ( ; i2 != busy_blocks.end(); ++i2) { i2->second.second->wait(); delete i2->second.first; } } catch (...) { } } //! \brief Returns number of owned blocks unsigned_type size() const { return free_blocks_size + busy_blocks.size(); } //! \brief Gives a hint for prefetching a block //! \param bid address of a block to be prefetched //! \return \c true if there was a free block to do prefetch and prefetching //! was scheduled, \c false otherwise //! \note If there are no free blocks available (all blocks //! are already in reading or read but not retrieved by user calling \c read //! method) calling \c hint function has no effect bool hint(bid_type bid) { // if block is already hinted, no need to hint it again if (in_prefetching(bid)) { STXXL_VERBOSE2("prefetch_pool::hint2 bid=" << bid << " was already cached"); return true; } if (free_blocks_size) // only if we have a free block { --free_blocks_size; block_type * block = free_blocks.back(); free_blocks.pop_back(); STXXL_VERBOSE2("prefetch_pool::hint bid=" << bid << " => prefetching"); request_ptr req = block->read(bid); busy_blocks[bid] = busy_entry(block, req); return true; } STXXL_VERBOSE2("prefetch_pool::hint bid=" << bid << " => no free blocks for prefetching"); return false; } bool hint(bid_type bid, write_pool & w_pool) { // if block is already hinted, no need to hint it again if (in_prefetching(bid)) { STXXL_VERBOSE2("prefetch_pool::hint2 bid=" << bid << " was already cached"); return true; } if (free_blocks_size) // only if we have a free block { --free_blocks_size; block_type * block = free_blocks.back(); free_blocks.pop_back(); if (w_pool.has_request(bid)) { busy_entry wp_request = w_pool.steal_request(bid); STXXL_VERBOSE1("prefetch_pool::hint2 bid=" << bid << " was in write cache at " << wp_request.first); assert(wp_request.first != 0); w_pool.add(block); //in exchange busy_blocks[bid] = wp_request; return true; } STXXL_VERBOSE2("prefetch_pool::hint2 bid=" << bid << " => prefetching"); request_ptr req = block->read(bid); busy_blocks[bid] = busy_entry(block, req); return true; } STXXL_VERBOSE2("prefetch_pool::hint2 bid=" << bid << " => no free blocks for prefetching"); return false; } bool invalidate(bid_type bid) { busy_blocks_iterator cache_el = busy_blocks.find(bid); if (cache_el == busy_blocks.end()) return false; // cancel request if it is a read request, there might be // write requests 'stolen' from a write_pool that may not be canceled if (cache_el->second.second->get_type() == request::READ) cache_el->second.second->cancel(); // finish the request cache_el->second.second->wait(); ++free_blocks_size; free_blocks.push_back(cache_el->second.first); busy_blocks.erase(cache_el); return true; } bool in_prefetching(bid_type bid) { return (busy_blocks.find(bid) != busy_blocks.end()); } //! \brief Reads block. If this block is cached block is not read but passed from the cache //! \param block block object, where data to be read to. If block was cached \c block 's //! ownership goes to the pool and block from cache is returned in \c block value. //! \param bid address of the block //! \warning \c block parameter must be allocated dynamically using \c new . //! \return request pointer object of read operation request_ptr read(block_type * & block, bid_type bid) { busy_blocks_iterator cache_el = busy_blocks.find(bid); if (cache_el == busy_blocks.end()) { // not cached STXXL_VERBOSE1("prefetch_pool::read bid=" << bid << " => no copy in cache, retrieving to " << block); return block->read(bid); } // cached STXXL_VERBOSE1("prefetch_pool::read bid=" << bid << " => copy in cache exists"); ++free_blocks_size; free_blocks.push_back(block); block = cache_el->second.first; request_ptr result = cache_el->second.second; busy_blocks.erase(cache_el); return result; } request_ptr read(block_type * & block, bid_type bid, write_pool & w_pool) { // try cache busy_blocks_iterator cache_el = busy_blocks.find(bid); if (cache_el != busy_blocks.end()) { // cached STXXL_VERBOSE1("prefetch_pool::read bid=" << bid << " => copy in cache exists"); ++free_blocks_size; free_blocks.push_back(block); block = cache_el->second.first; request_ptr result = cache_el->second.second; busy_blocks.erase(cache_el); return result; } // try w_pool cache if (w_pool.has_request(bid)) { busy_entry wp_request = w_pool.steal_request(bid); STXXL_VERBOSE1("prefetch_pool::read bid=" << bid << " was in write cache at " << wp_request.first); assert(wp_request.first != 0); w_pool.add(block); //in exchange block = wp_request.first; return wp_request.second; } // not cached STXXL_VERBOSE1("prefetch_pool::read bid=" << bid << " => no copy in cache, retrieving to " << block); return block->read(bid); } //! \brief Resizes size of the pool //! \param new_size desired size of the pool. If some //! blocks are used for prefetching, these blocks can't be freed. //! Only free blocks (not in prefetching) can be freed by reducing //! the size of the pool calling this method. //! \return new size of the pool unsigned_type resize(unsigned_type new_size) { int_type diff = int_type(new_size) - int_type(size()); if (diff > 0) { free_blocks_size += diff; while (--diff >= 0) free_blocks.push_back(new block_type); return size(); } while (diff < 0 && free_blocks_size > 0) { ++diff; --free_blocks_size; delete free_blocks.back(); free_blocks.pop_back(); } return size(); } }; //! \} __STXXL_END_NAMESPACE namespace std { template void swap(stxxl::prefetch_pool & a, stxxl::prefetch_pool & b) { a.swap(b); } } #endif // !STXXL_PREFETCH_POOL_HEADER // vim: et:ts=4:sw=4 stxxl-1.3.1/include/stxxl/bits/mng/adaptor.h0000644000175000017500000004135611513611117020652 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/mng/adaptor.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2002-2003 Roman Dementiev * Copyright (C) 2007 Johannes Singler * Copyright (C) 2009-2010 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_MNG_ADAPTOR_HEADER #define STXXL_MNG_ADAPTOR_HEADER #include #include __STXXL_BEGIN_NAMESPACE //! \addtogroup mnglayer //! //! \{ template class blocked_index { unsigned_type pos; unsigned_type block; unsigned_type offset; //! \invariant block * modulo + offset = pos void set(unsigned_type pos) { this->pos = pos; block = pos / modulo; offset = pos % modulo; } public: blocked_index() { set(0); } blocked_index(unsigned_type pos) { set(pos); } blocked_index(unsigned_type block, unsigned_type offset) { this->block = block; this->offset = offset; pos = block * modulo + offset; } void operator = (unsigned_type pos) { set(pos); } //pre-increment operator blocked_index & operator ++ () { ++pos; ++offset; if (offset == modulo) { offset = 0; ++block; } return *this; } //post-increment operator blocked_index operator ++ (int) { blocked_index former(*this); operator ++ (); return former; } //pre-increment operator blocked_index & operator -- () { --pos; if (offset == 0) { offset = modulo; --block; } --offset; return *this; } //post-increment operator blocked_index operator -- (int) { blocked_index former(*this); operator -- (); return former; } blocked_index & operator += (unsigned_type addend) { set(pos + addend); return *this; } blocked_index & operator >>= (unsigned_type shift) { set(pos >> shift); return *this; } operator unsigned_type () const { return pos; } const unsigned_type & get_block() const { return block; } const unsigned_type & get_offset() const { return offset; } }; #define STXXL_ADAPTOR_ARITHMETICS(pos) \ bool operator == (const _Self & a) const \ { \ return (a.pos == pos); \ } \ bool operator != (const _Self & a) const \ { \ return (a.pos != pos); \ } \ bool operator < (const _Self & a) const \ { \ return (pos < a.pos); \ } \ bool operator > (const _Self & a) const \ { \ return (pos > a.pos); \ } \ bool operator <= (const _Self & a) const \ { \ return (pos <= a.pos); \ } \ bool operator >= (const _Self & a) const \ { \ return (pos >= a.pos); \ } \ _Self operator + (pos_type off) const \ { \ return _Self(array, pos + off); \ } \ _Self operator - (pos_type off) const \ { \ return _Self(array, pos - off); \ } \ _Self & operator ++ () \ { \ pos++; \ return *this; \ } \ _Self operator ++ (int) \ { \ _Self tmp = *this; \ pos++; \ return tmp; \ } \ _Self & operator -- () \ { \ pos--; \ return *this; \ } \ _Self operator -- (int) \ { \ _Self tmp = *this; \ pos--; \ return tmp; \ } \ pos_type operator - (const _Self & a) const \ { \ return pos - a.pos; \ } \ _Self & operator -= (pos_type off) \ { \ pos -= off; \ return *this; \ } \ _Self & operator += (pos_type off) \ { \ pos += off; \ return *this; \ } template struct TwoToOneDimArrayAdaptorBase : public std::iterator { one_dim_array_type * array; pos_type pos; typedef pos_type _pos_type; typedef TwoToOneDimArrayAdaptorBase _Self; TwoToOneDimArrayAdaptorBase() { } TwoToOneDimArrayAdaptorBase(one_dim_array_type * a, pos_type p) : array(a), pos(p) { } TwoToOneDimArrayAdaptorBase(const TwoToOneDimArrayAdaptorBase & a) : array(a.array), pos(a.pos) { } STXXL_ADAPTOR_ARITHMETICS(pos) }; ////////////////////////////// #define BLOCK_ADAPTOR_OPERATORS(two_to_one_dim_array_adaptor_base) \ \ template \ inline two_to_one_dim_array_adaptor_base<_blk_sz, _run_type, __pos_type> & operator ++ ( \ two_to_one_dim_array_adaptor_base<_blk_sz, _run_type, __pos_type> & a) \ { \ a.pos++; \ return a; \ } \ \ template \ inline two_to_one_dim_array_adaptor_base<_blk_sz, _run_type, __pos_type> operator ++ ( \ two_to_one_dim_array_adaptor_base<_blk_sz, _run_type, __pos_type> & a, int) \ { \ two_to_one_dim_array_adaptor_base<_blk_sz, _run_type, __pos_type> tmp = a; \ a.pos++; \ return tmp; \ } \ \ template \ inline two_to_one_dim_array_adaptor_base<_blk_sz, _run_type, __pos_type> & operator -- ( \ two_to_one_dim_array_adaptor_base<_blk_sz, _run_type, __pos_type> & a) \ { \ a.pos--; \ return a; \ } \ \ template \ inline two_to_one_dim_array_adaptor_base<_blk_sz, _run_type, __pos_type> operator -- ( \ two_to_one_dim_array_adaptor_base<_blk_sz, _run_type, __pos_type> & a, int) \ { \ two_to_one_dim_array_adaptor_base<_blk_sz, _run_type, __pos_type> tmp = a; \ a.pos--; \ return tmp; \ } \ \ template \ inline two_to_one_dim_array_adaptor_base<_blk_sz, _run_type, __pos_type> & operator -= ( \ two_to_one_dim_array_adaptor_base<_blk_sz, _run_type, __pos_type> & a, \ typename two_to_one_dim_array_adaptor_base<_blk_sz, _run_type, __pos_type>::_pos_type off) \ { \ a.pos -= off; \ return a; \ } \ \ template \ inline two_to_one_dim_array_adaptor_base<_blk_sz, _run_type, __pos_type> & operator += ( \ two_to_one_dim_array_adaptor_base<_blk_sz, _run_type, __pos_type> & a, \ typename two_to_one_dim_array_adaptor_base<_blk_sz, _run_type, __pos_type>::_pos_type off) \ { \ a.pos += off; \ return a; \ } \ \ template \ inline two_to_one_dim_array_adaptor_base<_blk_sz, _run_type, __pos_type> operator + ( \ const two_to_one_dim_array_adaptor_base<_blk_sz, _run_type, __pos_type> & a, \ typename two_to_one_dim_array_adaptor_base<_blk_sz, _run_type, __pos_type>::_pos_type off) \ { \ return two_to_one_dim_array_adaptor_base<_blk_sz, _run_type, __pos_type>(a.array, a.pos + off); \ } \ \ template \ inline two_to_one_dim_array_adaptor_base<_blk_sz, _run_type, __pos_type> operator + ( \ typename two_to_one_dim_array_adaptor_base<_blk_sz, _run_type, __pos_type>::_pos_type off, \ const two_to_one_dim_array_adaptor_base<_blk_sz, _run_type, __pos_type> & a) \ { \ return two_to_one_dim_array_adaptor_base<_blk_sz, _run_type, __pos_type>(a.array, a.pos + off); \ } \ \ template \ inline two_to_one_dim_array_adaptor_base<_blk_sz, _run_type, __pos_type> operator - ( \ const two_to_one_dim_array_adaptor_base<_blk_sz, _run_type, __pos_type> & a, \ typename two_to_one_dim_array_adaptor_base<_blk_sz, _run_type, __pos_type>::_pos_type off) \ { \ return two_to_one_dim_array_adaptor_base<_blk_sz, _run_type, __pos_type>(a.array, a.pos - off); \ } #if 0 ////////////////////////// template > struct TwoToOneDimArrayRowAdaptor : public TwoToOneDimArrayAdaptorBase { typedef TwoToOneDimArrayRowAdaptor _Self; typedef TwoToOneDimArrayAdaptorBase _Parent; using _Parent::array; using _Parent::pos; TwoToOneDimArrayRowAdaptor() { } TwoToOneDimArrayRowAdaptor(one_dim_array_type * a, pos_type p) : TwoToOneDimArrayAdaptorBase(a, p) { } TwoToOneDimArrayRowAdaptor(const TwoToOneDimArrayRowAdaptor & a) : TwoToOneDimArrayAdaptorBase(a) { } data_type & operator * () { return array[(pos).get_block()][(pos).get_offset()]; } data_type * operator -> () const { return &(array[(pos).get_block()][(pos).get_offset()]); } data_type & operator [] (pos_type n) { n += pos; return array[(n) / dim_size][(n) % dim_size]; } const data_type & operator [] (pos_type n) const { n += pos; return array[(n) / dim_size][(n) % dim_size]; } STXXL_ADAPTOR_ARITHMETICS(pos) }; template > struct TwoToOneDimArrayColumnAdaptor : public TwoToOneDimArrayAdaptorBase { typedef TwoToOneDimArrayColumnAdaptor _Self; using TwoToOneDimArrayAdaptorBase::pos; using TwoToOneDimArrayAdaptorBase::array; TwoToOneDimArrayColumnAdaptor(one_dim_array_type * a, pos_type p) : TwoToOneDimArrayAdaptorBase(a, p) { } TwoToOneDimArrayColumnAdaptor(const _Self & a) : TwoToOneDimArrayAdaptorBase(a) { } data_type & operator * () { return array[(pos).get_offset()][(pos).get_block()]; } data_type * operator -> () const { return &(array[(pos).get_offset()][(pos).get_block()]); } const data_type & operator [] (pos_type n) const { n += pos; return array[(n) % dim_size][(n) / dim_size]; } data_type & operator [] (pos_type n) { n += pos; return array[(n) % dim_size][(n) / dim_size]; } STXXL_ADAPTOR_ARITHMETICS(pos) }; #endif template class ArrayOfSequencesIterator : public std::iterator { unsigned_type pos; unsigned_type offset; array_type * arrays; array_type * base; value_type * base_element; //! \invariant block * modulo + offset = pos void set(unsigned_type pos) { this->pos = pos; offset = pos % modulo; base = arrays + pos / modulo; base_element = base->elem; } public: ArrayOfSequencesIterator() { this->arrays = NULL; set(0); } ArrayOfSequencesIterator(array_type * arrays) { this->arrays = arrays; set(0); } ArrayOfSequencesIterator(array_type * arrays, unsigned_type pos) { this->arrays = arrays; set(pos); } void operator = (unsigned_type pos) { set(pos); } //pre-increment operator ArrayOfSequencesIterator & operator ++ () { ++pos; ++offset; if (offset == modulo) { offset = 0; ++base; base_element = base->elem; } return *this; } //post-increment operator ArrayOfSequencesIterator operator ++ (int) { ArrayOfSequencesIterator former(*this); operator ++ (); return former; } //pre-increment operator ArrayOfSequencesIterator & operator -- () { --pos; if (offset == 0) { offset = modulo; --base; base_element = base->elem; } --offset; return *this; } //post-increment operator ArrayOfSequencesIterator operator -- (int) { ArrayOfSequencesIterator former(*this); operator -- (); return former; } ArrayOfSequencesIterator & operator += (unsigned_type addend) { set(pos + addend); return *this; } ArrayOfSequencesIterator & operator -= (unsigned_type addend) { set(pos - addend); return *this; } ArrayOfSequencesIterator operator + (unsigned_type addend) const { return ArrayOfSequencesIterator(arrays, pos + addend); } ArrayOfSequencesIterator operator - (unsigned_type subtrahend) const { return ArrayOfSequencesIterator(arrays, pos - subtrahend); } unsigned_type operator - (const ArrayOfSequencesIterator & subtrahend) const { return pos - subtrahend.pos; } bool operator == (const ArrayOfSequencesIterator & aoai) const { return pos == aoai.pos; } bool operator != (const ArrayOfSequencesIterator & aoai) const { return pos != aoai.pos; } bool operator < (const ArrayOfSequencesIterator & aoai) const { return pos < aoai.pos; } bool operator <= (const ArrayOfSequencesIterator & aoai) const { return pos <= aoai.pos; } bool operator > (const ArrayOfSequencesIterator & aoai) const { return pos > aoai.pos; } bool operator >= (const ArrayOfSequencesIterator & aoai) const { return pos >= aoai.pos; } const value_type & operator * () const { return base_element[offset]; } value_type & operator * () { return base_element[offset]; } const value_type & operator -> () const { return &(base_element[offset]); } value_type & operator -> () { return &(base_element[offset]); } const value_type & operator [] (unsigned_type index) const { return arrays[index / modulo][index % modulo]; } value_type & operator [] (unsigned_type index) { return arrays[index / modulo][index % modulo]; } }; namespace helper { template class element_iterator_generator { }; // default case for blocks with fillers or other data: use ArrayOfSequenceIterator template class element_iterator_generator { typedef BlockType block_type; typedef typename block_type::value_type value_type; public: typedef ArrayOfSequencesIterator iterator; iterator operator () (block_type * blocks, unsigned_type offset) const { return iterator(blocks, offset); } }; // special case for completely filled blocks: use trivial pointers template class element_iterator_generator { typedef BlockType block_type; typedef typename block_type::value_type value_type; public: typedef value_type * iterator; iterator operator () (block_type * blocks, unsigned_type offset) const { return blocks[0].elem + offset; } }; } template struct element_iterator_traits { typedef typename helper::element_iterator_generator::iterator element_iterator; }; template inline typename element_iterator_traits::element_iterator make_element_iterator(BlockType * blocks, unsigned_type offset) { helper::element_iterator_generator iter_gen; return iter_gen(blocks, offset); } //! \} __STXXL_END_NAMESPACE #endif // !STXXL_MNG_ADAPTOR_HEADER // vim: et:ts=4:sw=4 stxxl-1.3.1/include/stxxl/bits/mng/diskallocator.h0000644000175000017500000001457111535663553022071 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/mng/diskallocator.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2002-2004 Roman Dementiev * Copyright (C) 2007 Johannes Singler * Copyright (C) 2009, 2010 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_DISKALLOCATOR_HEADER #define STXXL_DISKALLOCATOR_HEADER #include #include #include #include #include #include #include #include __STXXL_BEGIN_NAMESPACE //! \ingroup mnglayer //! \{ class DiskAllocator : private noncopyable { typedef std::pair place; struct FirstFit : public std::binary_function { bool operator () ( const place & entry, const stxxl::int64 size) const { return (entry.second >= size); } }; typedef std::map sortseq; stxxl::mutex mutex; sortseq free_space; stxxl::int64 free_bytes; stxxl::int64 disk_bytes; stxxl::file * storage; bool autogrow; void dump() const; void deallocation_error( stxxl::int64 block_pos, stxxl::int64 block_size, const sortseq::iterator & pred, const sortseq::iterator & succ) const; // expects the mutex to be locked to prevent concurrent access void add_free_region(stxxl::int64 block_pos, stxxl::int64 block_size); // expects the mutex to be locked to prevent concurrent access void grow_file(stxxl::int64 extend_bytes) { if (!extend_bytes) return; storage->set_size(disk_bytes + extend_bytes); add_free_region(disk_bytes, extend_bytes); disk_bytes += extend_bytes; } public: DiskAllocator(stxxl::file * storage, stxxl::int64 disk_size) : free_bytes(0), disk_bytes(0), storage(storage), autogrow(disk_size == 0) { grow_file(disk_size); } inline stxxl::int64 get_free_bytes() const { return free_bytes; } inline stxxl::int64 get_used_bytes() const { return disk_bytes - free_bytes; } inline stxxl::int64 get_total_bytes() const { return disk_bytes; } template void new_blocks(BIDArray & bids) { new_blocks(bids.begin(), bids.end()); } template void new_blocks(BID * begin, BID * end); #if 0 template void delete_blocks(const BIDArray & bids) { for (unsigned i = 0; i < bids.size(); ++i) delete_block(bids[i]); } #endif template void delete_block(const BID & bid) { scoped_mutex_lock lock(mutex); STXXL_VERBOSE2("DiskAllocator::delete_block<" << BLK_SIZE << ">(pos=" << bid.offset << ", size=" << bid.size << "), free:" << free_bytes << " total:" << disk_bytes); add_free_region(bid.offset, bid.size); } }; template void DiskAllocator::new_blocks(BID * begin, BID * end) { stxxl::int64 requested_size = 0; for (typename BIDArray::iterator cur = begin; cur != end; ++cur) { STXXL_VERBOSE2("Asking for a block with size: " << (cur->size)); requested_size += cur->size; } scoped_mutex_lock lock(mutex); STXXL_VERBOSE2("DiskAllocator::new_blocks, BLK_SIZE = " << BLK_SIZE << ", free:" << free_bytes << " total:" << disk_bytes << ", blocks: " << (end - begin) << " begin: " << static_cast(begin) << " end: " << static_cast(end) << ", requested_size=" << requested_size); if (free_bytes < requested_size) { if (!autogrow) { STXXL_ERRMSG("External memory block allocation error: " << requested_size << " bytes requested, " << free_bytes << " bytes free. Trying to extend the external memory space..."); } grow_file(requested_size); } // dump(); sortseq::iterator space; space = std::find_if(free_space.begin(), free_space.end(), bind2nd(FirstFit(), requested_size) _STXXL_FORCE_SEQUENTIAL); if (space == free_space.end() && requested_size == BLK_SIZE) { assert(end - begin == 1); STXXL_ERRMSG("Warning: Severe external memory space fragmentation!"); dump(); STXXL_ERRMSG("External memory block allocation error: " << requested_size << " bytes requested, " << free_bytes << " bytes free. Trying to extend the external memory space..."); grow_file(BLK_SIZE); space = std::find_if(free_space.begin(), free_space.end(), bind2nd(FirstFit(), requested_size) _STXXL_FORCE_SEQUENTIAL); } if (space != free_space.end()) { stxxl::int64 region_pos = (*space).first; stxxl::int64 region_size = (*space).second; free_space.erase(space); if (region_size > requested_size) free_space[region_pos + requested_size] = region_size - requested_size; for (stxxl::int64 pos = region_pos; begin != end; ++begin) { begin->offset = pos; pos += begin->size; } free_bytes -= requested_size; //dump(); return; } // no contiguous region found STXXL_VERBOSE1("Warning, when allocating an external memory space, no contiguous region found"); STXXL_VERBOSE1("It might harm the performance"); assert(requested_size > BLK_SIZE); assert(end - begin > 1); lock.unlock(); BID * middle = begin + ((end - begin) / 2); new_blocks(begin, middle); new_blocks(middle, end); } //! \} __STXXL_END_NAMESPACE #endif // !STXXL_DISKALLOCATOR_HEADER // vim: et:ts=4:sw=4 stxxl-1.3.1/include/stxxl/bits/mng/bid.h0000644000175000017500000001232211535513725017757 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/mng/bid.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2002-2004 Roman Dementiev * Copyright (C) 2009, 2010 Andreas Beckmann * Copyright (C) 2009 Johannes Singler * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_BID_HEADER #define STXXL_BID_HEADER #include #include #include #include #include #ifndef STXXL_VERBOSE_BLOCK_LIFE_CYCLE #define STXXL_VERBOSE_BLOCK_LIFE_CYCLE STXXL_VERBOSE2 #endif #define FMT_BID(_bid_) "[" << (_bid_).storage->get_allocator_id() << "]0x" << std::hex << std::setfill('0') << std::setw(8) << (_bid_).offset << "/0x" << std::setw(8) << (_bid_).size __STXXL_BEGIN_NAMESPACE //! \ingroup mnglayer //! \{ //! \brief Block identifier class //! Stores block identity, given by file and offset within the file template struct BID { enum { size = SIZE, //!< Block size t_size = SIZE //!< Blocks size, given by the parameter }; file * storage; //!< pointer to the file of the block stxxl::int64 offset; //!< offset within the file of the block BID() : storage(NULL), offset(0) { } bool valid() const { return storage != NULL; } BID(file * s, stxxl::int64 o) : storage(s), offset(o) { } BID(const BID & obj) : storage(obj.storage), offset(obj.offset) { } template explicit BID(const BID & obj) : storage(obj.storage), offset(obj.offset) { } template BID & operator = (const BID & obj) { storage = obj.storage; offset = obj.offset; return *this; } bool is_managed() const { return storage->get_allocator_id() != file::NO_ALLOCATOR; } }; //! \brief Specialization of block identifier class (BID) for variable size block size //! Stores block identity, given by file, offset within the file, and size of the block template <> struct BID<0> { file * storage; //!< pointer to the file of the block stxxl::int64 offset; //!< offset within the file of the block unsigned size; //!< size of the block in bytes enum { t_size = 0 //!< Blocks size, given by the parameter }; BID() : storage(NULL), offset(0), size(0) { } BID(file * f, stxxl::int64 o, unsigned s) : storage(f), offset(o), size(s) { } bool valid() const { return storage; } }; template bool operator == (const BID & a, const BID & b) { return (a.storage == b.storage) && (a.offset == b.offset) && (a.size == b.size); } template bool operator != (const BID & a, const BID & b) { return (a.storage != b.storage) || (a.offset != b.offset) || (a.size != b.size); } template std::ostream & operator << (std::ostream & s, const BID & bid) { // [0x12345678|0]0x00100000/0x00010000 // [file ptr|file id]offset/size s << "[" << bid.storage << "|"; if (bid.storage) s << bid.storage->get_allocator_id(); else s << "?"; s << "]0x" << std::hex << std::setfill('0') << std::setw(8) << bid.offset << "/0x" << std::setw(8) << bid.size << std::dec; return s; } #if 0 template class BIDArray : public std::vector > { public: BIDArray(std::vector >::size_type size = 0) : std::vector >(size) { } }; #endif template class BIDArray : private noncopyable { protected: unsigned_type _size; BID * array; public: typedef BID & reference; typedef BID * iterator; typedef const BID * const_iterator; BIDArray() : _size(0), array(NULL) { } iterator begin() { return array; } iterator end() { return array + _size; } BIDArray(unsigned_type size) : _size(size) { array = new BID[size]; } unsigned_type size() const { return _size; } reference operator [] (int_type i) { return array[i]; } void resize(unsigned_type newsize) { if (array) { STXXL_MSG("Warning: resizing nonempty BIDArray"); BID * tmp = array; array = new BID[newsize]; memcpy((void *)array, (void *)tmp, sizeof(BID) * (STXXL_MIN(_size, newsize))); delete[] tmp; _size = newsize; } else { array = new BID[newsize]; _size = newsize; } } ~BIDArray() { if (array) delete[] array; } }; //! \} __STXXL_END_NAMESPACE #endif // !STXXL_BID_HEADER // vim: et:ts=4:sw=4 stxxl-1.3.1/include/stxxl/bits/mng/typed_block.h0000644000175000017500000002625211513611117021515 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/mng/typed_block.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2002-2004 Roman Dementiev * Copyright (C) 2008-2010 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_TYPED_BLOCK_HEADER #define STXXL_TYPED_BLOCK_HEADER #include #include #include #ifndef STXXL_VERBOSE_TYPED_BLOCK #define STXXL_VERBOSE_TYPED_BLOCK STXXL_VERBOSE2 #endif __STXXL_BEGIN_NAMESPACE //! \ingroup mnglayer //! \{ template class filler_struct__ { typedef unsigned char byte_type; byte_type filler_array_[bytes]; public: filler_struct__() { STXXL_VERBOSE_TYPED_BLOCK("[" << (void *)this << "] filler_struct__ is constructed"); } }; template <> class filler_struct__<0> { typedef unsigned char byte_type; public: filler_struct__() { STXXL_VERBOSE_TYPED_BLOCK("[" << (void *)this << "] filler_struct__<> is constructed"); } }; //! \brief Contains data elements for \c stxxl::typed_block , not intended for direct use template class element_block { public: typedef T type; typedef T value_type; typedef T & reference; typedef const T & const_reference; typedef type * pointer; typedef pointer iterator; typedef const type * const_iterator; enum { size = Size_ //!< number of elements in the block }; //! Array of elements of type T T elem[size]; element_block() { STXXL_VERBOSE_TYPED_BLOCK("[" << (void *)this << "] element_block is constructed"); } //! An operator to access elements in the block reference operator [] (int i) { return elem[i]; } //! \brief Returns \c iterator pointing to the first element iterator begin() { return elem; } //! \brief Returns \c const_iterator pointing to the first element const_iterator begin() const { return elem; } //! \brief Returns \c const_iterator pointing to the first element const_iterator cbegin() const { return begin(); } //! \brief Returns \c iterator pointing to the end element iterator end() { return elem + size; } //! \brief Returns \c const_iterator pointing to the end element const_iterator end() const { return elem + size; } //! \brief Returns \c const_iterator pointing to the end element const_iterator cend() const { return end(); } }; //! \brief Contains BID references for \c stxxl::typed_block , not intended for direct use template class block_w_bids : public element_block { public: enum { raw_size = RawSize_, nbids = NBids_ }; typedef BID bid_type; //! Array of BID references bid_type ref[nbids]; //! An operator to access bid references bid_type & operator () (int i) { return ref[i]; } block_w_bids() { STXXL_VERBOSE_TYPED_BLOCK("[" << (void *)this << "] block_w_bids is constructed"); } }; template class block_w_bids: public element_block { public: enum { raw_size = RawSize_, nbids = 0 }; typedef BID bid_type; block_w_bids() { STXXL_VERBOSE_TYPED_BLOCK("[" << (void *)this << "] block_w_bids<> is constructed"); } }; //! \brief Contains per block information for \c stxxl::typed_block , not intended for direct use template class block_w_info : public block_w_bids) * NBids_ - sizeof(InfoType_)) / sizeof(T_)), RawSize_, NBids_> { public: //! \brief Type of per block information element typedef InfoType_ info_type; //! \brief Per block information element info_type info; block_w_info() { STXXL_VERBOSE_TYPED_BLOCK("[" << (void *)this << "] block_w_info is constructed"); } }; template class block_w_info: public block_w_bids) * NBids_) / sizeof(T_)), RawSize_, NBids_> { public: typedef void info_type; block_w_info() { STXXL_VERBOSE_TYPED_BLOCK("[" << (void *)this << "] block_w_info<> is constructed"); } }; //! \brief Contains per block filler for \c stxxl::typed_block , not intended for direct use template class add_filler : public BaseType_ { private: //! \brief Per block filler element filler_struct__ filler; public: add_filler() { STXXL_VERBOSE_TYPED_BLOCK("[" << (void *)this << "] add_filler is constructed"); } }; template class add_filler: public BaseType_ { public: add_filler() { STXXL_VERBOSE_TYPED_BLOCK("[" << (void *)this << "] add_filler<> is constructed"); } }; //! \brief Helper to compute the size of the filler , not intended for direct use template class expand_struct : public add_filler { }; //! \brief Block containing elements of fixed length //! \tparam RawSize_ size of block in bytes //! \tparam T_ type of block's records //! \tparam NRef_ number of block references (BIDs) that can be stored in the block (default is 0) //! \tparam InfoType_ type of per block information (default is no information - void) //! //! The data array of type T_ is contained in the parent class \c stxxl::element_block, see related information there. //! The BID array of references is contained in the parent class \c stxxl::block_w_bids, see related information there. //! The "per block information" is contained in the parent class \c stxxl::block_w_info, see related information there. //! \warning If \c RawSize_ > 2MB object(s) of this type can not be allocated on the stack (as a //! function variable for example), because Linux POSIX library limits the stack size for the //! main thread to (2MB - system page size) template class typed_block : public expand_struct, RawSize_> { typedef expand_struct, RawSize_> Base; public: typedef T_ value_type; typedef value_type & reference; typedef const value_type & const_reference; typedef value_type * pointer; typedef pointer iterator; typedef const value_type * const_pointer; typedef const_pointer const_iterator; enum constants { raw_size = RawSize_, //!< size of block in bytes size = Base::size, //!< number of elements in block has_only_data = (raw_size == (size * sizeof(value_type))) //!< no meta info, bids or (non-empty) fillers included in the block, allows value_type array addressing across block boundaries }; typedef BID bid_type; typed_block() { STXXL_STATIC_ASSERT(sizeof(typed_block) == raw_size); STXXL_VERBOSE_TYPED_BLOCK("[" << (void *)this << "] typed_block is constructed"); #if 0 assert(((long)this) % BLOCK_ALIGN == 0); #endif } #if 0 typed_block(const typed_block & tb) { STXXL_STATIC_ASSERT(sizeof(typed_block) == raw_size); STXXL_MSG("[" << (void *)this << "] typed_block is copy constructed from [" << (void *)&tb << "]"); STXXL_UNUSED(tb); } #endif /*! \brief Writes block to the disk(s) *! \param bid block identifier, points the file(disk) and position *! \param on_cmpl completion handler *! \return \c pointer_ptr object to track status I/O operation after the call */ request_ptr write(const bid_type & bid, completion_handler on_cmpl = default_completion_handler()) { STXXL_VERBOSE_BLOCK_LIFE_CYCLE("BLC:write " << FMT_BID(bid)); return bid.storage->awrite(this, bid.offset, raw_size, on_cmpl); } /*! \brief Reads block from the disk(s) *! \param bid block identifier, points the file(disk) and position *! \param on_cmpl completion handler *! \return \c pointer_ptr object to track status I/O operation after the call */ request_ptr read(const bid_type & bid, completion_handler on_cmpl = default_completion_handler()) { STXXL_VERBOSE_BLOCK_LIFE_CYCLE("BLC:read " << FMT_BID(bid)); return bid.storage->aread(this, bid.offset, raw_size, on_cmpl); } static void * operator new (size_t bytes) { unsigned_type meta_info_size = bytes % raw_size; STXXL_VERBOSE1("typed::block operator new: Meta info size: " << meta_info_size); void * result = aligned_alloc(bytes - meta_info_size, meta_info_size); #ifdef STXXL_VALGRIND_TYPED_BLOCK_INITIALIZE_ZERO memset(result, 0, bytes); #endif char * tmp = (char *)result; tmp += RawSize_; while (tmp < ((char *)result) + bytes) { tmp += RawSize_; } return result; } static void * operator new[] (size_t bytes) { unsigned_type meta_info_size = bytes % raw_size; STXXL_VERBOSE1("typed::block operator new[]: Meta info size: " << meta_info_size); void * result = aligned_alloc(bytes - meta_info_size, meta_info_size); #ifdef STXXL_VALGRIND_TYPED_BLOCK_INITIALIZE_ZERO memset(result, 0, bytes); #endif char * tmp = (char *)result; tmp += RawSize_; while (tmp < ((char *)result) + bytes) { tmp += RawSize_; } return result; } static void * operator new (size_t /*bytes*/, void * ptr) // construct object in existing memory { return ptr; } static void operator delete (void * ptr) { aligned_dealloc(ptr); } static void operator delete[] (void * ptr) { aligned_dealloc(ptr); } static void operator delete (void *, void *) { } #if 1 // STRANGE: implementing destructor makes g++ allocate // additional 4 bytes in the beginning of every array // of this type !? makes aligning to 4K boundaries difficult // // http://www.cc.gatech.edu/grads/j/Seung.Won.Jun/tips/pl/node4.html : // "One interesting thing is the array allocator requires more memory // than the array size multiplied by the size of an element, by a // difference of delta for metadata a compiler needs. It happens to // be 8 bytes long in g++." ~typed_block() { STXXL_VERBOSE_TYPED_BLOCK("[" << (void *)this << "] typed_block is destructed"); } #endif }; //! \} __STXXL_END_NAMESPACE #endif // !STXXL_TYPED_BLOCK_HEADER // vim: et:ts=4:sw=4 stxxl-1.3.1/include/stxxl/bits/mng/buf_istream.h0000644000175000017500000001102011312002443021472 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/mng/buf_istream.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2002-2004 Roman Dementiev * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_BUF_ISTREAM_HEADER #define STXXL_BUF_ISTREAM_HEADER #include #include #include __STXXL_BEGIN_NAMESPACE //! \addtogroup schedlayer //! \{ // a paranoid check #define BUF_ISTREAM_CHECK_END //! \brief Buffered input stream //! //! Reads data records from the stream of blocks. //! \remark Reading performed in the background, i.e. with overlapping of I/O and computation template class buf_istream { typedef BlkTp_ block_type; typedef BIDIteratorTp_ bid_iterator_type; buf_istream() { } protected: typedef block_prefetcher prefetcher_type; prefetcher_type * prefetcher; bid_iterator_type begin_bid, end_bid; int_type current_elem; block_type * current_blk; int_type * prefetch_seq; #ifdef BUF_ISTREAM_CHECK_END bool not_finished; #endif public: typedef typename block_type::reference reference; typedef buf_istream _Self; //! \brief Constructs input stream object //! \param _begin \c bid_iterator pointing to the first block of the stream //! \param _end \c bid_iterator pointing to the ( \b last + 1 ) block of the stream //! \param nbuffers number of buffers for internal use buf_istream(bid_iterator_type _begin, bid_iterator_type _end, int_type nbuffers) : current_elem(0) #ifdef BUF_ISTREAM_CHECK_END , not_finished(true) #endif { //int_type i; const unsigned_type ndisks = config::get_instance()->disks_number(); const int_type seq_length = _end - _begin; prefetch_seq = new int_type[seq_length]; // obvious schedule //for(int_type i = 0; i< seq_length; ++i) // prefetch_seq[i] = i; // optimal schedule nbuffers = STXXL_MAX(2 * ndisks, unsigned_type(nbuffers - 1)); compute_prefetch_schedule(_begin, _end, prefetch_seq, nbuffers, ndisks); prefetcher = new prefetcher_type(_begin, _end, prefetch_seq, nbuffers); current_blk = prefetcher->pull_block(); } //! \brief Input stream operator, reads in \c record //! \param record reference to the block record type, //! contains value of the next record in the stream after the call of the operator //! \return reference to itself (stream object) _Self & operator >> (reference record) { #ifdef BUF_ISTREAM_CHECK_END assert(not_finished); #endif record = current_blk->elem[current_elem++]; if (current_elem >= block_type::size) { current_elem = 0; #ifdef BUF_ISTREAM_CHECK_END not_finished = prefetcher->block_consumed(current_blk); #else prefetcher->block_consumed(current_blk); #endif } return (*this); } //! \brief Returns reference to the current record in the stream //! \return reference to the current record in the stream reference current() /* const */ { return current_blk->elem[current_elem]; } //! \brief Returns reference to the current record in the stream //! \return reference to the current record in the stream reference operator * () /* const */ { return current_blk->elem[current_elem]; } //! \brief Moves to the next record in the stream //! \return reference to itself after the advance _Self & operator ++ () { #ifdef BUF_ISTREAM_CHECK_END assert(not_finished); #endif current_elem++; if (current_elem >= block_type::size) { current_elem = 0; #ifdef BUF_ISTREAM_CHECK_END not_finished = prefetcher->block_consumed(current_blk); #else prefetcher->block_consumed(current_blk); #endif } return *this; } //! \brief Frees used internal objects virtual ~buf_istream() { delete prefetcher; delete[] prefetch_seq; } }; //! \} __STXXL_END_NAMESPACE #endif // !STXXL_BUF_ISTREAM_HEADER stxxl-1.3.1/include/stxxl/bits/mng/block_prefetcher.h0000644000175000017500000001717311535500414022522 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/mng/block_prefetcher.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2002-2004 Roman Dementiev * Copyright (C) 2009, 2010 Johannes Singler * Copyright (C) 2009 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_BLOCK_PREFETCHER_HEADER #define STXXL_BLOCK_PREFETCHER_HEADER #include #include #include #include #include __STXXL_BEGIN_NAMESPACE //! \addtogroup schedlayer //! \{ class set_switch_handler { onoff_switch & switch_; completion_handler on_compl; public: set_switch_handler(onoff_switch & switch__, const completion_handler & on_compl) : switch_(switch__), on_compl(on_compl) { } void operator () (request * req) { on_compl(req); //call before setting switch to on, otherwise, user has no way to wait for the completion handler to be executed switch_.on(); } }; //! \brief Encapsulates asynchronous prefetching engine //! //! \c block_prefetcher overlaps I/Os with consumption of read data. //! Utilizes optimal asynchronous prefetch scheduling (by Peter Sanders et.al.) template class block_prefetcher { block_prefetcher() { } typedef typename block_type::bid_type bid_type; protected: bid_iterator_type consume_seq_begin; bid_iterator_type consume_seq_end; unsigned_type seq_length; int_type * prefetch_seq; unsigned_type nextread; unsigned_type nextconsume; const int_type nreadblocks; block_type * read_buffers; request_ptr * read_reqs; bid_type * read_bids; onoff_switch * completed; int_type * pref_buffer; completion_handler do_after_fetch; block_type * wait(int_type iblock) { STXXL_VERBOSE1("block_prefetcher: waiting block " << iblock); { stats::scoped_wait_timer wait_timer(stats::WAIT_OP_READ); completed[iblock].wait_for_on(); } STXXL_VERBOSE1("block_prefetcher: finished waiting block " << iblock); int_type ibuffer = pref_buffer[iblock]; STXXL_VERBOSE1("block_prefetcher: returning buffer " << ibuffer); assert(ibuffer >= 0 && ibuffer < nreadblocks); return (read_buffers + ibuffer); } public: //! \brief Constructs an object and immediately starts prefetching //! \param _cons_begin \c bid_iterator pointing to the \c bid of the first block to be consumed //! \param _cons_end \c bid_iterator pointing to the \c bid of the ( \b last + 1 ) block of consumption sequence //! \param _pref_seq gives the prefetch order, is a pointer to the integer array that contains //! the indices of the blocks in the consumption sequence //! \param _prefetch_buf_size amount of prefetch buffers to use block_prefetcher( bid_iterator_type _cons_begin, bid_iterator_type _cons_end, int_type * _pref_seq, int_type _prefetch_buf_size, completion_handler do_after_fetch = default_completion_handler() ) : consume_seq_begin(_cons_begin), consume_seq_end(_cons_end), seq_length(_cons_end - _cons_begin), prefetch_seq(_pref_seq), nextread(STXXL_MIN(unsigned_type(_prefetch_buf_size), seq_length)), nextconsume(0), nreadblocks(nextread), do_after_fetch(do_after_fetch) { STXXL_VERBOSE1("block_prefetcher: seq_length=" << seq_length); STXXL_VERBOSE1("block_prefetcher: _prefetch_buf_size=" << _prefetch_buf_size); assert(seq_length > 0); assert(_prefetch_buf_size > 0); int_type i; read_buffers = new block_type[nreadblocks]; read_reqs = new request_ptr[nreadblocks]; read_bids = new bid_type[nreadblocks]; pref_buffer = new int_type[seq_length]; std::fill(pref_buffer, pref_buffer + seq_length, -1); completed = new onoff_switch[seq_length]; for (i = 0; i < nreadblocks; ++i) { assert(prefetch_seq[i] < int_type(seq_length)); assert(prefetch_seq[i] >= 0); read_bids[i] = *(consume_seq_begin + prefetch_seq[i]); STXXL_VERBOSE1("block_prefetcher: reading block " << i << " prefetch_seq[" << i << "]=" << prefetch_seq[i] << " @ " << &read_buffers[i] << " @ " << read_bids[i]); read_reqs[i] = read_buffers[i].read( read_bids[i], set_switch_handler(*(completed + prefetch_seq[i]), do_after_fetch)); pref_buffer[prefetch_seq[i]] = i; } } //! \brief Pulls next unconsumed block from the consumption sequence //! \return Pointer to the already prefetched block from the internal buffer pool block_type * pull_block() { STXXL_VERBOSE1("block_prefetcher: pulling a block"); return wait(nextconsume++); } //! \brief Exchanges buffers between prefetcher and application //! \param buffer pointer to the consumed buffer. After call if return value is true \c buffer //! contains valid pointer to the next unconsumed prefetched buffer. //! \remark parameter \c buffer must be value returned by \c pull_block() or \c block_consumed() methods //! \return \c false if there are no blocks to prefetch left, \c true if consumption sequence is not emptied bool block_consumed(block_type * & buffer) { int_type ibuffer = buffer - read_buffers; STXXL_VERBOSE1("block_prefetcher: buffer " << ibuffer << " consumed"); if (read_reqs[ibuffer].valid()) read_reqs[ibuffer]->wait(); read_reqs[ibuffer] = NULL; if (nextread < seq_length) { assert(ibuffer >= 0 && ibuffer < nreadblocks); int_type next_2_prefetch = prefetch_seq[nextread++]; STXXL_VERBOSE1("block_prefetcher: prefetching block " << next_2_prefetch); assert((next_2_prefetch < int_type(seq_length)) && (next_2_prefetch >= 0)); assert(!completed[next_2_prefetch].is_on()); pref_buffer[next_2_prefetch] = ibuffer; read_bids[ibuffer] = *(consume_seq_begin + next_2_prefetch); read_reqs[ibuffer] = read_buffers[ibuffer].read( read_bids[ibuffer], set_switch_handler(*(completed + next_2_prefetch), do_after_fetch) ); } if (nextconsume >= seq_length) return false; buffer = wait(nextconsume++); return true; } // no more consumable blocks available, but can't delete the prefetcher, // because not all blocks may have been returned, yet bool empty() const { return nextconsume >= seq_length; } // index of the next element in the consume sequence unsigned_type pos() const { return nextconsume; } //! \brief Frees used memory ~block_prefetcher() { for (int_type i = 0; i < nreadblocks; ++i) if (read_reqs[i].valid()) read_reqs[i]->wait(); delete[] read_reqs; delete[] read_bids; delete[] completed; delete[] pref_buffer; delete[] read_buffers; } }; //! \} __STXXL_END_NAMESPACE #endif // !STXXL_BLOCK_PREFETCHER_HEADER stxxl-1.3.1/include/stxxl/bits/mng/block_alloc.h0000644000175000017500000001311111531237734021461 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/mng/block_alloc.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2002-2007 Roman Dementiev * Copyright (C) 2007-2009 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_MNG__BLOCK_ALLOC_H #define STXXL_MNG__BLOCK_ALLOC_H #include #include #include #include __STXXL_BEGIN_NAMESPACE //! \ingroup mnglayer //! \weakgroup alloc Allocation functors //! Standard allocation strategies encapsulated in functors //! \{ //! \brief example disk allocation scheme functor //! \remarks model of \b allocation_strategy concept struct basic_allocation_strategy { basic_allocation_strategy(int disks_begin, int disks_end); basic_allocation_strategy(); int operator () (int i) const; static const char * name(); }; //! \brief striping disk allocation scheme functor //! \remarks model of \b allocation_strategy concept struct striping { int begin, diff; public: striping(int b, int e) : begin(b), diff(e - b) { } striping() : begin(0) { diff = config::get_instance()->disks_number(); } int operator () (int i) const { return begin + i % diff; } static const char * name() { return "striping"; } }; //! \brief fully randomized disk allocation scheme functor //! \remarks model of \b allocation_strategy concept struct FR : public striping { private: random_number rnd; public: FR(int b, int e) : striping(b, e) { } FR() : striping() { } int operator () (int /*i*/) const { return begin + rnd(diff); } static const char * name() { return "fully randomized striping"; } }; //! \brief simple randomized disk allocation scheme functor //! \remarks model of \b allocation_strategy concept struct SR : public striping { private: int offset; void init() { random_number rnd; offset = rnd(diff); } public: SR(int b, int e) : striping(b, e) { init(); } SR() : striping() { init(); } int operator () (int i) const { return begin + (i + offset) % diff; } static const char * name() { return "simple randomized striping"; } }; //! \brief randomized cycling disk allocation scheme functor //! \remarks model of \b allocation_strategy concept struct RC : public striping { private: std::vector perm; void init() { for (int i = 0; i < diff; i++) perm[i] = i; stxxl::random_number rnd; std::random_shuffle(perm.begin(), perm.end(), rnd _STXXL_FORCE_SEQUENTIAL); } public: RC(int b, int e) : striping(b, e), perm(diff) { init(); } RC() : striping(), perm(diff) { init(); } int operator () (int i) const { return begin + perm[i % diff]; } static const char * name() { return "randomized cycling striping"; } }; struct RC_disk : public RC { RC_disk(int b, int e) : RC(b, e) { } RC_disk() : RC(config::get_instance()->regular_disk_range().first, config::get_instance()->regular_disk_range().second) { } static const char * name() { return "Randomized cycling striping on regular disks"; } }; struct RC_flash : public RC { RC_flash(int b, int e) : RC(b, e) { } RC_flash() : RC(config::get_instance()->flash_range().first, config::get_instance()->flash_range().second) { } static const char * name() { return "Randomized cycling striping on flash devices"; } }; //! \brief 'single disk' disk allocation scheme functor //! \remarks model of \b allocation_strategy concept struct single_disk { const int disk; single_disk(int d, int = 0) : disk(d) { } single_disk() : disk(0) { } int operator () (int /*i*/) const { return disk; } static const char * name() { return "single disk"; } }; //! \brief Allocator functor adaptor //! Gives offset to disk number sequence defined in constructor template struct offset_allocator { BaseAllocator_ base; int_type offset; //! \brief Creates functor based on instance of \c BaseAllocator_ functor //! with offset \c offset_ //! \param offset_ offset //! \param base_ used to create a copy offset_allocator(int_type offset_, const BaseAllocator_ & base_) : base(base_), offset(offset_) { } //! \brief Creates functor based on instance of \c BaseAllocator_ functor //! \param base_ used to create a copy offset_allocator(const BaseAllocator_ & base_) : base(base_), offset(0) { } //! \brief Creates functor based on default \c BaseAllocator_ functor offset_allocator() : offset(0) { } int operator () (int_type i) const { return base(offset + i); } int_type get_offset() const { return offset; } void set_offset(int_type i) { offset = i; } }; #ifndef STXXL_DEFAULT_ALLOC_STRATEGY #define STXXL_DEFAULT_ALLOC_STRATEGY stxxl::RC #endif //! \} __STXXL_END_NAMESPACE #endif // !STXXL_MNG__BLOCK_ALLOC_H // vim: et:ts=4:sw=4 stxxl-1.3.1/include/stxxl/bits/mng/config.h0000644000175000017500000000654311535442512020471 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/mng/config.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2002-2005 Roman Dementiev * Copyright (C) 2008, 2009 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_MNG__CONFIG_H #define STXXL_MNG__CONFIG_H #include #include #include #include #include __STXXL_BEGIN_NAMESPACE //! \ingroup mnglayer //! \brief Access point to disks properties //! \remarks is a singleton class config : public singleton { friend class singleton; struct DiskEntry { std::string path; std::string io_impl; stxxl::int64 size; bool delete_on_exit; bool autogrow; }; std::vector disks_props; // in disks_props, flash devices come after all regular disks unsigned first_flash; config() { const char * cfg_path = getenv("STXXLCFG"); if (cfg_path) init(cfg_path); else init(); } ~config() { for (unsigned i = 0; i < disks_props.size(); ++i) { if (disks_props[i].delete_on_exit || disks_props[i].autogrow) { if (!disks_props[i].autogrow) { STXXL_ERRMSG("Removing disk file created from default configuration: " << disks_props[i].path); } unlink(disks_props[i].path.c_str()); } } } void init(const char * config_path = "./.stxxl"); public: //! \brief Returns number of disks available to user //! \return number of disks inline unsigned disks_number() const { return disks_props.size(); } //! \brief Returns contiguous range of regular disks w/o flash devices in the array of all disks //! \return range [begin, end) of regular disk indices inline std::pair regular_disk_range() const { return std::pair(0, first_flash); } //! \brief Returns contiguous range of flash devices in the array of all disks //! \return range [begin, end) of flash device indices inline std::pair flash_range() const { return std::pair(first_flash, (unsigned)disks_props.size()); } //! \brief Returns path of disks //! \param disk disk's identifier //! \return string that contains the disk's path name inline const std::string & disk_path(int disk) const { return disks_props[disk].path; } //! \brief Returns disk size //! \param disk disk's identifier //! \return disk size in bytes inline stxxl::int64 disk_size(int disk) const { return disks_props[disk].size; } //! \brief Returns name of I/O implementation of particular disk //! \param disk disk's identifier inline const std::string & disk_io_impl(int disk) const { return disks_props[disk].io_impl; } }; __STXXL_END_NAMESPACE #endif // !STXXL_MNG__CONFIG_H // vim: et:ts=4:sw=4 stxxl-1.3.1/include/stxxl/bits/mng/buf_ostream.h0000644000175000017500000000616611026753412021532 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/mng/buf_ostream.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2002-2004 Roman Dementiev * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_BUF_OSTREAM_HEADER #define STXXL_BUF_OSTREAM_HEADER #include __STXXL_BEGIN_NAMESPACE //! \addtogroup schedlayer //! \{ //! \brief Buffered output stream //! //! Writes data records to the stream of blocks. //! \remark Writing performed in the background, i.e. with overlapping of I/O and computation template class buf_ostream { typedef BlkTp_ block_type; typedef BIDIteratorTp_ bid_iterator_type; protected: buffered_writer writer; bid_iterator_type current_bid; int_type current_elem; block_type * current_blk; public: typedef typename block_type::const_reference const_reference; typedef typename block_type::reference reference; typedef buf_ostream _Self; //! \brief Constructs output stream object //! \param first_bid \c bid_iterator pointing to the first block of the stream //! \param nbuffers number of buffers for internal use buf_ostream(bid_iterator_type first_bid, int_type nbuffers) : writer(nbuffers, nbuffers / 2), current_bid(first_bid), current_elem(0) { current_blk = writer.get_free_block(); } //! \brief Output stream operator, writes out \c record //! \param record const reference to block record type, containing a value of record to write to the stream //! \return reference to itself (stream object) _Self & operator << (const_reference record) { current_blk->elem[current_elem++] = record; if (current_elem >= block_type::size) { current_elem = 0; current_blk = writer.write(current_blk, *(current_bid++)); } return (*this); } //! \brief Returns reference to the current record //! \return reference to the current record reference current() { return current_blk->elem[current_elem]; } //! \brief Returns reference to the current record //! \return reference to the current record reference operator * () { return current_blk->elem[current_elem]; } //! \brief Moves to the next record in the stream //! \return reference to itself after the advance _Self & operator ++ () { ++current_elem; if (current_elem >= block_type::size) { current_elem = 0; current_blk = writer.write(current_blk, *(current_bid++)); } return (*this); } //! \brief Deallocates internal objects virtual ~buf_ostream() { assert(current_elem == 0); } }; //! \} __STXXL_END_NAMESPACE #endif // !STXXL_BUF_OSTREAM_HEADER stxxl-1.3.1/include/stxxl/bits/mng/buf_writer.h0000644000175000017500000001633711535540436021402 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/mng/buf_writer.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2002-2004 Roman Dementiev * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_BUFFERED_WRITER_HEADER #define STXXL_BUFFERED_WRITER_HEADER #include #include #include #include __STXXL_BEGIN_NAMESPACE //! \weakgroup schedlayer Block scheduling sublayer //! \ingroup mnglayer //! Group of classes which help in scheduling //! sequences of read and write requests //! via prefetching and buffered writing //! \{ //! \brief Encapsulates asynchronous buffered block writing engine //! //! \c buffered_writer overlaps I/Os with filling of output buffer. template class buffered_writer { buffered_writer() { } protected: typedef typename block_type::bid_type bid_type; const unsigned_type nwriteblocks; block_type * write_buffers; bid_type * write_bids; request_ptr * write_reqs; const unsigned_type writebatchsize; std::vector free_write_blocks; // contains free write blocks std::vector busy_write_blocks; // blocks that are in writing, notice that if block is not in free_ // an not in busy then block is not yet filled struct batch_entry { stxxl::int64 offset; int_type ibuffer; batch_entry(stxxl::int64 o, int b) : offset(o), ibuffer(b) { } }; struct batch_entry_cmp { bool operator () (const batch_entry & a, const batch_entry & b) const { return (a.offset > b.offset); } }; typedef std::priority_queue, batch_entry_cmp> batch_type; batch_type batch_write_blocks; // sorted sequence of blocks to write public: //! \brief Constructs an object //! \param write_buf_size number of write buffers to use //! \param write_batch_size number of blocks to accumulate in //! order to flush write requests (bulk buffered writing) buffered_writer(unsigned_type write_buf_size, unsigned_type write_batch_size) : nwriteblocks((write_buf_size > 2) ? write_buf_size : 2), writebatchsize(write_batch_size ? write_batch_size : 1) { write_buffers = new block_type[nwriteblocks]; write_reqs = new request_ptr[nwriteblocks]; write_bids = new bid_type[nwriteblocks]; for (unsigned_type i = 0; i < nwriteblocks; i++) free_write_blocks.push_back(i); disk_queues::get_instance()->set_priority_op(request_queue::WRITE); } //! \brief Returns free block from the internal buffer pool //! \return pointer to the block from the internal buffer pool block_type * get_free_block() { int_type ibuffer; for (std::vector::iterator it = busy_write_blocks.begin(); it != busy_write_blocks.end(); ++it) { if (write_reqs[ibuffer = (*it)]->poll()) { busy_write_blocks.erase(it); free_write_blocks.push_back(ibuffer); break; } } if (UNLIKELY(free_write_blocks.empty())) { int_type size = busy_write_blocks.size(); request_ptr * reqs = new request_ptr[size]; int_type i = 0; for ( ; i < size; ++i) { reqs[i] = write_reqs[busy_write_blocks[i]]; } int_type completed = wait_any(reqs, size); int_type completed_global = busy_write_blocks[completed]; delete[] reqs; busy_write_blocks.erase(busy_write_blocks.begin() + completed); return (write_buffers + completed_global); } ibuffer = free_write_blocks.back(); free_write_blocks.pop_back(); return (write_buffers + ibuffer); } //! \brief Submits block for writing //! \param filled_block pointer to the block //! \remark parameter \c filled_block must be value returned by \c get_free_block() or \c write() methods //! \param bid block identifier, a place to write data of the \c filled_block //! \return pointer to the new free block from the pool block_type * write(block_type * filled_block, const bid_type & bid) // writes filled_block and returns a new block { if (batch_write_blocks.size() >= writebatchsize) { // flush batch while (!batch_write_blocks.empty()) { int_type ibuffer = batch_write_blocks.top().ibuffer; batch_write_blocks.pop(); if (write_reqs[ibuffer].valid()) write_reqs[ibuffer]->wait(); write_reqs[ibuffer] = write_buffers[ibuffer].write(write_bids[ibuffer]); busy_write_blocks.push_back(ibuffer); } } // STXXL_MSG("Adding write request to batch"); int_type ibuffer = filled_block - write_buffers; write_bids[ibuffer] = bid; batch_write_blocks.push(batch_entry(bid.offset, ibuffer)); return get_free_block(); } //! \brief Flushes not yet written buffers void flush() { int_type ibuffer; while (!batch_write_blocks.empty()) { ibuffer = batch_write_blocks.top().ibuffer; batch_write_blocks.pop(); if (write_reqs[ibuffer].valid()) write_reqs[ibuffer]->wait(); write_reqs[ibuffer] = write_buffers[ibuffer].write(write_bids[ibuffer]); busy_write_blocks.push_back(ibuffer); } for (std::vector::const_iterator it = busy_write_blocks.begin(); it != busy_write_blocks.end(); it++) { ibuffer = *it; write_reqs[ibuffer]->wait(); } assert(batch_write_blocks.empty()); free_write_blocks.clear(); busy_write_blocks.clear(); for (unsigned_type i = 0; i < nwriteblocks; i++) free_write_blocks.push_back(i); } //! \brief Flushes not yet written buffers and frees used memory virtual ~buffered_writer() { int_type ibuffer; while (!batch_write_blocks.empty()) { ibuffer = batch_write_blocks.top().ibuffer; batch_write_blocks.pop(); if (write_reqs[ibuffer].valid()) write_reqs[ibuffer]->wait(); write_reqs[ibuffer] = write_buffers[ibuffer].write(write_bids[ibuffer]); busy_write_blocks.push_back(ibuffer); } for (std::vector::const_iterator it = busy_write_blocks.begin(); it != busy_write_blocks.end(); it++) { ibuffer = *it; write_reqs[ibuffer]->wait(); } delete[] write_reqs; delete[] write_buffers; delete[] write_bids; } }; //! \} __STXXL_END_NAMESPACE #endif // !STXXL_BUFFERED_WRITER_HEADER stxxl-1.3.1/include/stxxl/bits/mng/read_write_pool.h0000644000175000017500000001241411421061551022366 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/mng/read_write_pool.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2009 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_MNG_READ_WRITE_POOL_H #define STXXL_MNG_READ_WRITE_POOL_H #include #include __STXXL_BEGIN_NAMESPACE //! \addtogroup schedlayer //! \{ //! \brief Implements dynamically resizable buffered writing and prefetched reading pool template class read_write_pool : private noncopyable { public: typedef BlockType block_type; typedef typename block_type::bid_type bid_type; typedef unsigned_type size_type; protected: typedef write_pool write_pool_type; typedef prefetch_pool prefetch_pool_type; write_pool_type * w_pool; prefetch_pool_type * p_pool; bool delete_pools; public: //! \brief Constructs pool //! \param init_size_prefetch initial number of blocks in the prefetch pool //! \param init_size_write initial number of blocks in the write pool explicit read_write_pool(size_type init_size_prefetch = 1, size_type init_size_write = 1) : delete_pools(true) { w_pool = new write_pool_type(init_size_write); p_pool = new prefetch_pool_type(init_size_prefetch); } _STXXL_DEPRECATED(read_write_pool(prefetch_pool_type & p_pool, write_pool_type & w_pool)) : w_pool(&w_pool), p_pool(&p_pool), delete_pools(false) { } void swap(read_write_pool & obj) { std::swap(w_pool, obj.w_pool); std::swap(p_pool, obj.p_pool); std::swap(delete_pools, obj.delete_pools); } //! \brief Waits for completion of all ongoing requests and frees memory virtual ~read_write_pool() { if (delete_pools) { delete w_pool; delete p_pool; } } //! \brief Returns number of blocks owned by the write_pool size_type size_write() const { return w_pool->size(); } //! \brief Returns number of blocks owned by the prefetch_pool size_type size_prefetch() const { return p_pool->size(); } //! \brief Resizes size of the pool //! \param new_size new size of the pool after the call void resize_write(size_type new_size) { w_pool->resize(new_size); } //! \brief Resizes size of the pool //! \param new_size new size of the pool after the call void resize_prefetch(size_type new_size) { p_pool->resize(new_size); } // WRITE POOL METHODS //! \brief Passes a block to the pool for writing //! \param block block to write. Ownership of the block goes to the pool. //! \c block must be allocated dynamically with using \c new . //! \param bid location, where to write //! \warning \c block must be allocated dynamically with using \c new . //! \return request object of the write operation request_ptr write(block_type * & block, bid_type bid) { request_ptr result = w_pool->write(block, bid); // if there is a copy of this block in the prefetch pool, // it is now a stale copy, so invalidate it and re-hint the block if (p_pool->invalidate(bid)) p_pool->hint(bid, *w_pool); return result; } //! \brief Take out a block from the pool //! \return pointer to the block. Ownership of the block goes to the caller. block_type * steal() { return w_pool->steal(); } void add(block_type * & block) { w_pool->add(block); } // PREFETCH POOL METHODS //! \brief Gives a hint for prefetching a block //! \param bid address of a block to be prefetched //! \return \c true if there was a free block to do prefetch and prefetching //! was scheduled, \c false otherwise //! \note If there are no free blocks available (all blocks //! are already in reading or read but not retrieved by user calling \c read //! method) calling \c hint function has no effect bool hint(bid_type bid) { return p_pool->hint(bid, *w_pool); } bool invalidate(bid_type bid) { return p_pool->invalidate(bid); } //! \brief Reads block. If this block is cached block is not read but passed from the cache //! \param block block object, where data to be read to. If block was cached \c block 's //! ownership goes to the pool and block from cache is returned in \c block value. //! \param bid address of the block //! \warning \c block parameter must be allocated dynamically using \c new . //! \return request pointer object of read operation request_ptr read(block_type * & block, bid_type bid) { return p_pool->read(block, bid, *w_pool); } }; //! \} __STXXL_END_NAMESPACE namespace std { template void swap(stxxl::read_write_pool & a, stxxl::read_write_pool & b) { a.swap(b); } } #endif // !STXXL_MNG_READ_WRITE_POOL_H // vim: et:ts=4:sw=4 stxxl-1.3.1/include/stxxl/bits/mng/mng.h0000644000175000017500000001757011535151017020004 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/mng/mng.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2002-2007 Roman Dementiev * Copyright (C) 2007, 2009 Johannes Singler * Copyright (C) 2008-2010 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_MNG_HEADER #define STXXL_MNG_HEADER #include #include #include #include #include #include #include #include #include #ifdef STXXL_BOOST_CONFIG #include #endif #ifdef BOOST_MSVC #include #endif #include #include #include #include #include #include #include #include #include #include __STXXL_BEGIN_NAMESPACE //! \defgroup mnglayer Block management layer //! Group of classes which help controlling external memory space, //! managing disks, and allocating and deallocating blocks of external storage //! \{ //! \brief Block manager class //! Manages allocation and deallocation of blocks in multiple/single disk setting //! \remarks is a singleton class block_manager : public singleton { friend class singleton; DiskAllocator ** disk_allocators; file ** disk_files; unsigned ndisks; block_manager(); protected: template void new_blocks_int( const unsigned_type nblocks, const DiskAssignFunctor & functor, unsigned_type offset, BIDIteratorClass out); public: //! \brief Allocates new blocks //! Allocates new blocks according to the strategy //! given by \b functor and stores block identifiers //! to the range [ \b bidbegin, \b bidend) //! Allocation will be lined up with previous partial allocations //! of \b offset blocks. //! \param functor object of model of \b allocation_strategy concept //! \param bidbegin bidirectional BID iterator object //! \param bidend bidirectional BID iterator object //! \param offset advance for \b functor to line up partial allocations template void new_blocks( const DiskAssignFunctor & functor, BIDIteratorClass bidbegin, BIDIteratorClass bidend, unsigned_type offset = 0) { typedef typename std::iterator_traits::value_type bid_type; new_blocks_int(std::distance(bidbegin, bidend), functor, offset, bidbegin); } //! Allocates new blocks according to the strategy //! given by \b functor and stores block identifiers //! to the output iterator \b out //! Allocation will be lined up with previous partial allocations //! of \b offset blocks. //! \param nblocks the number of blocks to allocate //! \param functor object of model of \b allocation_strategy concept //! \param out iterator object of OutputIterator concept //! \param offset advance for \b functor to line up partial allocations //! //! The \c BlockType template parameter defines the type of block to allocate template void new_blocks( const unsigned_type nblocks, const DiskAssignFunctor & functor, BIDIteratorClass out, unsigned_type offset = 0) { typedef typename BlockType::bid_type bid_type; new_blocks_int(nblocks, functor, offset, out); } //! Allocates a new block according to the strategy //! given by \b functor and stores the block identifier //! to bid. //! Allocation will be lined up with previous partial allocations //! of \b offset blocks. //! \param functor object of model of \b allocation_strategy concept //! \param bid BID to store the block identifier //! \param offset advance for \b functor to line up partial allocations template void new_block(const DiskAssignFunctor & functor, BID & bid, unsigned_type offset = 0) { new_blocks_int >(1, functor, offset, &bid); } //! \brief Deallocates blocks //! Deallocates blocks in the range [ \b bidbegin, \b bidend) //! \param bidbegin iterator object of \b bid_iterator concept //! \param bidend iterator object of \b bid_iterator concept template void delete_blocks(const BIDIteratorClass & bidbegin, const BIDIteratorClass & bidend); //! \brief Deallocates a block //! \param bid block identifier template void delete_block(const BID & bid); ~block_manager(); }; template void block_manager::new_blocks_int( const unsigned_type nblocks, const DiskAssignFunctor & functor, unsigned_type offset, OutputIterator out) { typedef BIDType bid_type; typedef BIDArray bid_array_type; int_type * bl = new int_type[ndisks]; bid_array_type * disk_bids = new bid_array_type[ndisks]; file ** disk_ptrs = new file *[nblocks]; memset(bl, 0, ndisks * sizeof(int_type)); unsigned_type i; for (i = 0; i < nblocks; ++i) { const int disk = functor(offset + i); disk_ptrs[i] = disk_files[disk]; bl[disk]++; } for (i = 0; i < ndisks; ++i) { if (bl[i]) { disk_bids[i].resize(bl[i]); disk_allocators[i]->new_blocks(disk_bids[i]); } } memset(bl, 0, ndisks * sizeof(int_type)); OutputIterator it = out; for (i = 0; i != nblocks; ++it, ++i) { const int disk = disk_ptrs[i]->get_allocator_id(); bid_type bid(disk_ptrs[i], disk_bids[disk][bl[disk]++].offset); *it = bid; STXXL_VERBOSE_BLOCK_LIFE_CYCLE("BLC:new " << FMT_BID(bid)); } delete[] bl; delete[] disk_bids; delete[] disk_ptrs; } template void block_manager::delete_block(const BID & bid) { // do not uncomment it //assert(bid.storage->get_allocator_id() < config::get_instance()->disks_number()); if (!bid.is_managed()) return; // self managed disk STXXL_VERBOSE_BLOCK_LIFE_CYCLE("BLC:delete " << FMT_BID(bid)); assert(bid.storage->get_allocator_id() >= 0); disk_allocators[bid.storage->get_allocator_id()]->delete_block(bid); disk_files[bid.storage->get_allocator_id()]->discard(bid.offset, bid.size); } template void block_manager::delete_blocks( const BIDIteratorClass & bidbegin, const BIDIteratorClass & bidend) { for (BIDIteratorClass it = bidbegin; it != bidend; it++) { delete_block(*it); } } // in bytes #ifndef STXXL_DEFAULT_BLOCK_SIZE #define STXXL_DEFAULT_BLOCK_SIZE(type) (2 * 1024 * 1024) // use traits #endif class FileCreator { public: _STXXL_DEPRECATED( static file * create(const std::string & io_impl, const std::string & filename, int options, int queue_id = file::DEFAULT_QUEUE, int allocator_id = file::NO_ALLOCATOR) ) { return create_file(io_impl, filename, options, queue_id, allocator_id); } }; //! \} __STXXL_END_NAMESPACE #endif // !STXXL_MNG_HEADER // vim: et:ts=4:sw=4 stxxl-1.3.1/include/stxxl/bits/mng/write_pool.h0000644000175000017500000002167411535500414021405 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/mng/write_pool.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2003-2004 Roman Dementiev * Copyright (C) 2009 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_WRITE_POOL_HEADER #define STXXL_WRITE_POOL_HEADER #include #ifdef STXXL_BOOST_CONFIG #include #endif #include #include #include __STXXL_BEGIN_NAMESPACE //! \addtogroup schedlayer //! \{ //! \brief Implements dynamically resizable buffered writing pool template class write_pool : private noncopyable { public: typedef BlockType block_type; typedef typename block_type::bid_type bid_type; // a hack to make wait_any work with busy_entry type struct busy_entry { block_type * block; request_ptr req; bid_type bid; busy_entry() : block(NULL) { } busy_entry(const busy_entry & a) : block(a.block), req(a.req), bid(a.bid) { } busy_entry(block_type * & bl, request_ptr & r, bid_type & bi) : block(bl), req(r), bid(bi) { } operator request_ptr () { return req; } }; typedef typename std::list::iterator free_blocks_iterator; typedef typename std::list::iterator busy_blocks_iterator; protected: // contains free write blocks std::list free_blocks; // blocks that are in writing std::list busy_blocks; unsigned_type free_blocks_size, busy_blocks_size; public: //! \brief Constructs pool //! \param init_size initial number of blocks in the pool explicit write_pool(unsigned_type init_size = 1) : free_blocks_size(init_size), busy_blocks_size(0) { unsigned_type i = 0; for ( ; i < init_size; ++i) free_blocks.push_back(new block_type); } void swap(write_pool & obj) { std::swap(free_blocks, obj.free_blocks); std::swap(busy_blocks, obj.busy_blocks); std::swap(free_blocks_size, obj.free_blocks_size); std::swap(busy_blocks_size, busy_blocks_size); } //! \brief Waits for completion of all ongoing write requests and frees memory virtual ~write_pool() { STXXL_VERBOSE2("write_pool::~write_pool free_blocks_size: " << free_blocks_size << " busy_blocks_size: " << busy_blocks_size); while (!free_blocks.empty()) { delete free_blocks.back(); free_blocks.pop_back(); } try { for (busy_blocks_iterator i2 = busy_blocks.begin(); i2 != busy_blocks.end(); ++i2) { i2->req->wait(); delete i2->block; } } catch (...) { } } //! \brief Returns number of owned blocks unsigned_type size() const { return free_blocks_size + busy_blocks_size; } //! \brief Passes a block to the pool for writing //! \param block block to write. Ownership of the block goes to the pool. //! \c block must be allocated dynamically with using \c new . //! \param bid location, where to write //! \warning \c block must be allocated dynamically with using \c new . //! \return request object of the write operation request_ptr write(block_type * & block, bid_type bid) { STXXL_VERBOSE1("write_pool::write: " << block << " @ " << bid); for (busy_blocks_iterator i2 = busy_blocks.begin(); i2 != busy_blocks.end(); ++i2) { if (i2->bid == bid) { assert(i2->block != block); STXXL_VERBOSE1("WAW dependency"); // try to cancel the obsolete request i2->req->cancel(); // invalidate the bid of the stale write request, // prevents prefetch_pool from stealing a stale block i2->bid.storage = 0; } } request_ptr result = block->write(bid); ++busy_blocks_size; busy_blocks.push_back(busy_entry(block, result, bid)); block = NULL; // prevent caller from using the block any further return result; } //! \brief Take out a block from the pool //! \return pointer to the block. Ownership of the block goes to the caller. block_type * steal() { assert(size() > 0); if (free_blocks_size) { STXXL_VERBOSE1("write_pool::steal : " << free_blocks_size << " free blocks available"); --free_blocks_size; block_type * p = free_blocks.back(); free_blocks.pop_back(); return p; } STXXL_VERBOSE1("write_pool::steal : all " << busy_blocks_size << " are busy"); busy_blocks_iterator completed = wait_any(busy_blocks.begin(), busy_blocks.end()); assert(completed != busy_blocks.end()); // we got something reasonable from wait_any assert(completed->req->poll()); // and it is *really* completed block_type * p = completed->block; busy_blocks.erase(completed); --busy_blocks_size; check_all_busy(); // for debug return p; } // deprecated name for the steal() _STXXL_DEPRECATED(block_type * get()) { return steal(); } //! \brief Resizes size of the pool //! \param new_size new size of the pool after the call void resize(unsigned_type new_size) { int_type diff = int_type(new_size) - int_type(size()); if (diff > 0) { free_blocks_size += diff; while (--diff >= 0) free_blocks.push_back(new block_type); return; } while (++diff <= 0) delete steal(); } _STXXL_DEPRECATED(request_ptr get_request(bid_type bid)) { busy_blocks_iterator i2 = busy_blocks.begin(); for ( ; i2 != busy_blocks.end(); ++i2) { if (i2->bid == bid) return i2->req; } return request_ptr(); } bool has_request(bid_type bid) { for (busy_blocks_iterator i2 = busy_blocks.begin(); i2 != busy_blocks.end(); ++i2) { if (i2->bid == bid) return true; } return false; } _STXXL_DEPRECATED(block_type * steal(bid_type bid)) { busy_blocks_iterator i2 = busy_blocks.begin(); for ( ; i2 != busy_blocks.end(); ++i2) { if (i2->bid == bid) { block_type * p = i2->block; i2->req->wait(); busy_blocks.erase(i2); --busy_blocks_size; return p; } } return NULL; } // returns a block and a (potentially unfinished) I/O request associated with it std::pair steal_request(bid_type bid) { for (busy_blocks_iterator i2 = busy_blocks.begin(); i2 != busy_blocks.end(); ++i2) { if (i2->bid == bid) { // remove busy block from list, request has not yet been waited for! block_type * blk = i2->block; request_ptr req = i2->req; busy_blocks.erase(i2); --busy_blocks_size; // hand over block and (unfinished) request to caller return std::pair(blk, req); } } // not matching request found, return a dummy return std::pair((block_type *)NULL, request_ptr()); } void add(block_type * & block) { free_blocks.push_back(block); ++free_blocks_size; block = NULL; // prevent caller from using the block any further } protected: void check_all_busy() { busy_blocks_iterator cur = busy_blocks.begin(); int_type cnt = 0; while (cur != busy_blocks.end()) { if (cur->req->poll()) { free_blocks.push_back(cur->block); cur = busy_blocks.erase(cur); ++cnt; --busy_blocks_size; ++free_blocks_size; continue; } ++cur; } STXXL_VERBOSE1("write_pool::check_all_busy : " << cnt << " are completed out of " << busy_blocks_size + cnt << " busy blocks"); } }; //! \} __STXXL_END_NAMESPACE namespace std { template void swap(stxxl::write_pool & a, stxxl::write_pool & b) { a.swap(b); } } #endif // !STXXL_WRITE_POOL_HEADER // vim: et:ts=4:sw=4 stxxl-1.3.1/include/stxxl/bits/mng/block_alloc_interleaved.h0000644000175000017500000000753711535151017024053 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/mng/block_alloc_interleaved.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2002, 2003 Roman Dementiev * Copyright (C) 2007-2009, 2011 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_INTERLEAVED_ALLOC_HEADER #define STXXL_INTERLEAVED_ALLOC_HEADER #include #include #include __STXXL_BEGIN_NAMESPACE #define CHECK_RUN_BOUNDS(pos) struct interleaved_striping { protected: int_type nruns; int begindisk; int diff; interleaved_striping(int_type nruns, int begindisk, int diff) : nruns(nruns), begindisk(begindisk), diff(diff) { } public: interleaved_striping(int_type _nruns, const striping & strategy) : nruns(_nruns), begindisk(strategy.begin), diff(strategy.diff) { } int operator () (int_type i) const { return begindisk + (i / nruns) % diff; } }; struct interleaved_FR : public interleaved_striping { random_number rnd; interleaved_FR(int_type _nruns, const FR & strategy) : interleaved_striping(_nruns, strategy.begin, strategy.diff) { } int operator () (int_type /*i*/) const { return begindisk + rnd(diff); } }; struct interleaved_SR : public interleaved_striping { std::vector offsets; interleaved_SR(int_type _nruns, const SR & strategy) : interleaved_striping(_nruns, strategy.begin, strategy.diff) { random_number rnd; for (int_type i = 0; i < nruns; i++) offsets.push_back(rnd(diff)); } int operator () (int_type i) const { return begindisk + (i / nruns + offsets[i % nruns]) % diff; } }; struct interleaved_RC : public interleaved_striping { std::vector > perms; interleaved_RC(int_type _nruns, const RC & strategy) : interleaved_striping(_nruns, strategy.begin, strategy.diff), perms(nruns, std::vector(diff)) { for (int_type i = 0; i < nruns; i++) { for (int j = 0; j < diff; j++) perms[i][j] = j; random_number rnd; std::random_shuffle(perms[i].begin(), perms[i].end(), rnd _STXXL_FORCE_SEQUENTIAL); } } int operator () (int_type i) const { return begindisk + perms[i % nruns][(i / nruns) % diff]; } }; struct first_disk_only : public interleaved_striping { first_disk_only(int_type _nruns, const single_disk & strategy) : interleaved_striping(_nruns, strategy.disk, 1) { } int operator () (int_type) const { return begindisk; } }; template struct interleaved_alloc_traits { }; template <> struct interleaved_alloc_traits { typedef interleaved_striping strategy; }; template <> struct interleaved_alloc_traits { typedef interleaved_FR strategy; }; template <> struct interleaved_alloc_traits { typedef interleaved_SR strategy; }; template <> struct interleaved_alloc_traits { typedef interleaved_RC strategy; }; template <> struct interleaved_alloc_traits { // FIXME! HACK! typedef interleaved_RC strategy; }; template <> struct interleaved_alloc_traits { // FIXME! HACK! typedef interleaved_RC strategy; }; template <> struct interleaved_alloc_traits { typedef first_disk_only strategy; }; __STXXL_END_NAMESPACE #endif // !STXXL_INTERLEAVED_ALLOC_HEADER // vim: et:ts=4:sw=4 stxxl-1.3.1/include/stxxl/bits/algo/0000755000175000017500000000000011536252421017203 5ustar andreasandreasstxxl-1.3.1/include/stxxl/bits/algo/async_schedule.h0000644000175000017500000000441711310151601022337 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/algo/async_schedule.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2002 Roman Dementiev * Copyright (C) 2009 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ // Implements the "prudent prefetching" as described in // D. Hutchinson, P. Sanders, J. S. Vitter: Duality between prefetching // and queued writing on parallel disks, 2005 // DOI: 10.1137/S0097539703431573 #ifndef STXXL_ASYNC_SCHEDULE_HEADER #define STXXL_ASYNC_SCHEDULE_HEADER #include __STXXL_BEGIN_NAMESPACE void compute_prefetch_schedule( const int_type * first, const int_type * last, int_type * out_first, int_type m, int_type D); inline void compute_prefetch_schedule( int_type * first, int_type * last, int_type * out_first, int_type m, int_type D) { compute_prefetch_schedule(static_cast(first), last, out_first, m, D); } template void compute_prefetch_schedule( const run_type & input, int_type * out_first, int_type m, int_type D) { const int_type L = input.size(); int_type * disks = new int_type[L]; for (int_type i = 0; i < L; ++i) disks[i] = input[i].bid.storage->get_physical_device_id(); compute_prefetch_schedule(disks, disks + L, out_first, m, D); delete[] disks; } template void compute_prefetch_schedule( bid_iterator_type input_begin, bid_iterator_type input_end, int_type * out_first, int_type m, int_type D) { const int_type L = input_end - input_begin; int_type * disks = new int_type[L]; int_type i = 0; for (bid_iterator_type it = input_begin; it != input_end; ++it, ++i) disks[i] = it->storage->get_physical_device_id(); compute_prefetch_schedule(disks, disks + L, out_first, m, D); delete[] disks; } __STXXL_END_NAMESPACE #endif // !STXXL_ASYNC_SCHEDULE_HEADER // vim: et:ts=4:sw=4 stxxl-1.3.1/include/stxxl/bits/algo/adaptor.h0000644000175000017500000001440711513611117021010 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/algo/adaptor.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2002 Roman Dementiev * Copyright (C) 2010 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_ALGO_ADAPTOR_HEADER #define STXXL_ALGO_ADAPTOR_HEADER #include #include __STXXL_BEGIN_NAMESPACE template struct RunsToBIDArrayAdaptor : public TwoToOneDimArrayAdaptorBase<_run_type *, BID<_blk_sz>, __pos_type> { typedef RunsToBIDArrayAdaptor<_blk_sz, _run_type, __pos_type> _Self; typedef BID<_blk_sz> data_type; enum { block_size = _blk_sz }; unsigned_type dim_size; typedef TwoToOneDimArrayAdaptorBase<_run_type *, BID<_blk_sz>, __pos_type> _Parent; using _Parent::array; using _Parent::pos; RunsToBIDArrayAdaptor(_run_type ** a, __pos_type p, unsigned_type d) : TwoToOneDimArrayAdaptorBase<_run_type *, BID<_blk_sz>, __pos_type>(a, p), dim_size(d) { } RunsToBIDArrayAdaptor(const _Self & a) : TwoToOneDimArrayAdaptorBase<_run_type *, BID<_blk_sz>, __pos_type>(a), dim_size(a.dim_size) { } const _Self & operator = (const _Self & a) { array = a.array; pos = a.pos; dim_size = a.dim_size; return *this; } data_type & operator * () { CHECK_RUN_BOUNDS(pos); return (BID<_blk_sz>&)((*(array[(pos) % dim_size]))[(pos) / dim_size].bid); } const data_type * operator -> () const { CHECK_RUN_BOUNDS(pos); return &((*(array[(pos) % dim_size])[(pos) / dim_size].bid)); } data_type & operator [] (__pos_type n) const { n += pos; CHECK_RUN_BOUNDS(n); return (BID<_blk_sz>&)((*(array[(n) % dim_size]))[(n) / dim_size].bid); } }; BLOCK_ADAPTOR_OPERATORS(RunsToBIDArrayAdaptor) template struct RunsToBIDArrayAdaptor2 : public TwoToOneDimArrayAdaptorBase<_run_type *, BID<_blk_sz>, __pos_type> { typedef RunsToBIDArrayAdaptor2<_blk_sz, _run_type, __pos_type> _Self; typedef BID<_blk_sz> data_type; typedef TwoToOneDimArrayAdaptorBase<_run_type *, BID<_blk_sz>, __pos_type> ParentClass_; using ParentClass_::pos; using ParentClass_::array; enum { block_size = _blk_sz }; __pos_type w, h, K; RunsToBIDArrayAdaptor2(_run_type ** a, __pos_type p, int_type _w, int_type _h) : TwoToOneDimArrayAdaptorBase<_run_type *, BID<_blk_sz>, __pos_type>(a, p), w(_w), h(_h), K(_w * _h) { } RunsToBIDArrayAdaptor2(const _Self & a) : TwoToOneDimArrayAdaptorBase<_run_type *, BID<_blk_sz>, __pos_type>(a), w(a.w), h(a.h), K(a.K) { } const _Self & operator = (const _Self & a) { array = a.array; pos = a.pos; w = a.w; h = a.h; K = a.K; return *this; } data_type & operator * () { register __pos_type i = pos - K; if (i < 0) return (BID<_blk_sz>&)((*(array[(pos) % w]))[(pos) / w].bid); register __pos_type _w = w; _w--; return (BID<_blk_sz>&)((*(array[(i) % _w]))[h + (i / _w)].bid); } const data_type * operator -> () const { register __pos_type i = pos - K; if (i < 0) return &((*(array[(pos) % w])[(pos) / w].bid)); register __pos_type _w = w; _w--; return &((*(array[(i) % _w])[h + (i / _w)].bid)); } data_type & operator [] (__pos_type n) const { n += pos; register __pos_type i = n - K; if (i < 0) return (BID<_blk_sz>&)((*(array[(n) % w]))[(n) / w].bid); register __pos_type _w = w; _w--; return (BID<_blk_sz>&)((*(array[(i) % _w]))[h + (i / _w)].bid); } }; BLOCK_ADAPTOR_OPERATORS(RunsToBIDArrayAdaptor2) template struct trigger_entry_iterator { typedef trigger_entry_iterator _Self; typedef typename std::iterator_traits::value_type::bid_type bid_type; // STL typedefs typedef bid_type value_type; typedef std::random_access_iterator_tag iterator_category; typedef int_type difference_type; typedef value_type * pointer; typedef value_type & reference; trigger_iterator_type value; trigger_entry_iterator(const _Self & a) : value(a.value) { } trigger_entry_iterator(trigger_iterator_type v) : value(v) { } bid_type & operator * () { return value->bid; } bid_type * operator -> () const { return &(value->bid); } const bid_type & operator [] (int_type n) const { return (value + n)->bid; } bid_type & operator [] (int_type n) { return (value + n)->bid; } _Self & operator ++ () { value++; return *this; } _Self operator ++ (int) { _Self __tmp = *this; value++; return __tmp; } _Self & operator -- () { value--; return *this; } _Self operator -- (int) { _Self __tmp = *this; value--; return __tmp; } bool operator == (const _Self & a) const { return value == a.value; } bool operator != (const _Self & a) const { return value != a.value; } _Self operator += (int_type n) { value += n; return *this; } _Self operator -= (int_type n) { value -= n; return *this; } int_type operator - (const _Self & a) const { return value - a.value; } int_type operator + (const _Self & a) const { return value + a.value; } }; template inline trigger_entry_iterator make_bid_iterator(Iterator iter) { return trigger_entry_iterator(iter); } __STXXL_END_NAMESPACE #endif // !STXXL_ALGO_ADAPTOR_HEADER stxxl-1.3.1/include/stxxl/bits/algo/random_shuffle.h0000644000175000017500000003224411520237720022353 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/algo/random_shuffle.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2007 Manuel Krings * Copyright (C) 2007 Markus Westphal * Copyright (C) 2009, 2010 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_RANDOM_SHUFFLE_HEADER #define STXXL_RANDOM_SHUFFLE_HEADER // TODO: improve main memory consumption in recursion // (free stacks buffers) // TODO: shuffle small input in internal memory #include #include #include __STXXL_BEGIN_NAMESPACE //! \addtogroup stlalgo //! \{ //! \brief External equivalent of std::random_shuffle //! \param first begin of the range to shuffle //! \param last end of the range to shuffle //! \param rand random number generator object (functor) //! \param M number of bytes for internal use //! \param AS parallel disk allocation strategy //! //! - BlockSize_ size of the block to use for external memory data structures //! - PageSize_ page size in blocks to use for external memory data structures template void random_shuffle(ExtIterator_ first, ExtIterator_ last, RandomNumberGenerator_ & rand, unsigned_type M, AllocStrategy_ AS = STXXL_DEFAULT_ALLOC_STRATEGY()) { STXXL_UNUSED(AS); // FIXME: Why is this not being used? typedef typename ExtIterator_::value_type value_type; typedef typename stxxl::STACK_GENERATOR::result stack_type; typedef typename stack_type::block_type block_type; STXXL_VERBOSE1("random_shuffle: Plain Version"); STXXL_STATIC_ASSERT(int(BlockSize_) < 0 && "This implementation was never tested. Please report to the stxxl developers if you have an ExtIterator_ that works with this implementation."); stxxl::int64 n = last - first; // the number of input elements // make sure we have at least 6 blocks + 1 page if (M < 6 * BlockSize_ + PageSize_ * BlockSize_) { STXXL_ERRMSG("random_shuffle: insufficient memory, " << M << " bytes supplied,"); M = 6 * BlockSize_ + PageSize_ * BlockSize_; STXXL_ERRMSG("random_shuffle: increasing to " << M << " bytes (6 blocks + 1 page)"); } int_type k = M / (3 * BlockSize_); // number of buckets stxxl::int64 i, j, size = 0; value_type * temp_array; typedef typename stxxl::VECTOR_GENERATOR::result temp_vector_type; temp_vector_type * temp_vector; STXXL_VERBOSE1("random_shuffle: " << M / BlockSize_ - k << " write buffers for " << k << " buckets"); stxxl::read_write_pool pool(0, M / BlockSize_ - k); // no read buffers and M/B-k write buffers stack_type ** buckets; // create and put buckets into container buckets = new stack_type *[k]; for (j = 0; j < k; j++) buckets[j] = new stack_type(pool, 0); ///// Reading input ///////////////////// typedef typename stream::streamify_traits::stream_type input_stream; input_stream in = stxxl::stream::streamify(first, last); // distribute input into random buckets int_type random_bucket = 0; for (i = 0; i < n; ++i) { random_bucket = rand(k); buckets[random_bucket]->push(*in); // reading the current input element ++in; // go to the next input element } ///// Processing ////////////////////// // resize buffers pool.resize_write(0); pool.resize_prefetch(PageSize_); unsigned_type space_left = M - k * BlockSize_ - PageSize_ * BlockSize_; // remaining int space ExtIterator_ Writer = first; ExtIterator_ it = first; for (i = 0; i < k; i++) { STXXL_VERBOSE1("random_shuffle: bucket no " << i << " contains " << buckets[i]->size() << " elements"); } // shuffle each bucket for (i = 0; i < k; i++) { buckets[i]->set_prefetch_aggr(PageSize_); size = buckets[i]->size(); // does the bucket fit into memory? if (size * sizeof(value_type) < space_left) { STXXL_VERBOSE1("random_shuffle: no recursion"); // copy bucket into temp. array temp_array = new value_type[size]; for (j = 0; j < size; j++) { temp_array[j] = buckets[i]->top(); buckets[i]->pop(); } // shuffle potentially_parallel:: random_shuffle(temp_array, temp_array + size, rand); // write back for (j = 0; j < size; j++) { *Writer = temp_array[j]; ++Writer; } // free memory delete[] temp_array; } else { STXXL_VERBOSE1("random_shuffle: recursion"); // copy bucket into temp. stxxl::vector temp_vector = new temp_vector_type(size); for (j = 0; j < size; j++) { (*temp_vector)[j] = buckets[i]->top(); buckets[i]->pop(); } pool.resize_prefetch(0); space_left += PageSize_ * BlockSize_; STXXL_VERBOSE1("random_shuffle: Space left: " << space_left); // recursive shuffle stxxl::random_shuffle(temp_vector->begin(), temp_vector->end(), rand, space_left); pool.resize_prefetch(PageSize_); // write back for (j = 0; j < size; j++) { *Writer = (*temp_vector)[j]; ++Writer; } // free memory delete temp_vector; } // free bucket delete buckets[i]; space_left += BlockSize_; } delete[] buckets; } //! \brief External equivalent of std::random_shuffle (specialization for stxxl::vector) //! \param first begin of the range to shuffle //! \param last end of the range to shuffle //! \param rand random number generator object (functor) //! \param M number of bytes for internal use template void random_shuffle(stxxl::vector_iterator first, stxxl::vector_iterator last, RandomNumberGenerator_ & rand, unsigned_type M) { typedef stxxl::vector_iterator ExtIterator_; typedef typename ExtIterator_::value_type value_type; typedef typename stxxl::STACK_GENERATOR::result stack_type; typedef typename stack_type::block_type block_type; STXXL_VERBOSE1("random_shuffle: Vector Version"); // make sure we have at least 6 blocks + 1 page if (M < 6 * BlockSize_ + PageSize_ * BlockSize_) { STXXL_ERRMSG("random_shuffle: insufficient memory, " << M << " bytes supplied,"); M = 6 * BlockSize_ + PageSize_ * BlockSize_; STXXL_ERRMSG("random_shuffle: increasing to " << M << " bytes (6 blocks + 1 page)"); } stxxl::int64 n = last - first; // the number of input elements int_type k = M / (3 * BlockSize_); // number of buckets stxxl::int64 i, j, size = 0; value_type * temp_array; typedef typename stxxl::VECTOR_GENERATOR::result temp_vector_type; temp_vector_type * temp_vector; stxxl::read_write_pool pool(0, M / BlockSize_ - k); // no read buffers and M/B-k write buffers stack_type ** buckets; // create and put buckets into container buckets = new stack_type *[k]; for (j = 0; j < k; j++) buckets[j] = new stack_type(pool, 0); typedef buf_istream buf_istream_type; typedef buf_ostream buf_ostream_type; first.flush(); // flush container // create prefetching stream, buf_istream_type in(first.bid(), last.bid() + ((last.block_offset()) ? 1 : 0), 2); // create buffered write stream for blocks buf_ostream_type out(first.bid(), 2); ExtIterator_ _cur = first - first.block_offset(); // leave part of the block before _begin untouched (e.g. copy) for ( ; _cur != first; ++_cur) { typename ExtIterator_::value_type tmp; in >> tmp; out << tmp; } ///// Reading input ///////////////////// // distribute input into random buckets int_type random_bucket = 0; for (i = 0; i < n; ++i, ++_cur) { random_bucket = rand(k); typename ExtIterator_::value_type tmp; in >> tmp; buckets[random_bucket]->push(tmp); // reading the current input element } ///// Processing ////////////////////// // resize buffers pool.resize_write(0); pool.resize_prefetch(PageSize_); unsigned_type space_left = M - k * BlockSize_ - PageSize_ * BlockSize_; // remaining int space for (i = 0; i < k; i++) { STXXL_VERBOSE1("random_shuffle: bucket no " << i << " contains " << buckets[i]->size() << " elements"); } // shuffle each bucket for (i = 0; i < k; i++) { buckets[i]->set_prefetch_aggr(PageSize_); size = buckets[i]->size(); // does the bucket fit into memory? if (size * sizeof(value_type) < space_left) { STXXL_VERBOSE1("random_shuffle: no recursion"); // copy bucket into temp. array temp_array = new value_type[size]; for (j = 0; j < size; j++) { temp_array[j] = buckets[i]->top(); buckets[i]->pop(); } // shuffle potentially_parallel:: random_shuffle(temp_array, temp_array + size, rand); // write back for (j = 0; j < size; j++) { typename ExtIterator_::value_type tmp; tmp = temp_array[j]; out << tmp; } // free memory delete[] temp_array; } else { STXXL_VERBOSE1("random_shuffle: recursion"); // copy bucket into temp. stxxl::vector temp_vector = new temp_vector_type(size); for (j = 0; j < size; j++) { (*temp_vector)[j] = buckets[i]->top(); buckets[i]->pop(); } pool.resize_prefetch(0); space_left += PageSize_ * BlockSize_; STXXL_VERBOSE1("random_shuffle: Space left: " << space_left); // recursive shuffle stxxl::random_shuffle(temp_vector->begin(), temp_vector->end(), rand, space_left); pool.resize_prefetch(PageSize_); // write back for (j = 0; j < size; j++) { typename ExtIterator_::value_type tmp; tmp = (*temp_vector)[j]; out << tmp; } // free memory delete temp_vector; } // free bucket delete buckets[i]; space_left += BlockSize_; } delete[] buckets; // leave part of the block after _end untouched if (last.block_offset()) { ExtIterator_ _last_block_end = last + (block_type::size - last.block_offset()); for ( ; _cur != _last_block_end; ++_cur) { typename ExtIterator_::value_type tmp; in >> tmp; out << tmp; } } } //! \brief External equivalent of std::random_shuffle (specialization for stxxl::vector) //! \param first begin of the range to shuffle //! \param last end of the range to shuffle //! \param M number of bytes for internal use template inline void random_shuffle(stxxl::vector_iterator first, stxxl::vector_iterator last, unsigned_type M) { stxxl::random_number<> rand; stxxl::random_shuffle(first, last, rand, M); } //! \} __STXXL_END_NAMESPACE #endif // !STXXL_RANDOM_SHUFFLE_HEADER // vim: et:ts=4:sw=4 stxxl-1.3.1/include/stxxl/bits/algo/stable_ksort.h0000644000175000017500000004467011535540436022070 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/algo/stable_ksort.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2003 Roman Dementiev * Copyright (C) 2008 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_STABLE_KSORT_HEADER #define STXXL_STABLE_KSORT_HEADER // it is a first try: distribution sort without sampling // I rework the stable_ksort when I would have a time #include #include #include #include #include #include #include #ifndef STXXL_VERBOSE_STABLE_KSORT #define STXXL_VERBOSE_STABLE_KSORT STXXL_VERBOSE1 #endif __STXXL_BEGIN_NAMESPACE //! \addtogroup stlalgo //! \{ /*! \internal */ namespace stable_ksort_local { template void classify_block(type_ * begin, type_ * end, type_key * & out, int_type * bucket, unsigned_type offset, unsigned shift) { for (type_ * p = begin; p < end; p++, out++) // count & create references { out->ptr = p; typename type_::key_type key = p->key(); int_type ibucket = (key - offset) >> shift; out->key = key; bucket[ibucket]++; } } template struct type_key { typedef typename type::key_type key_type; key_type key; type * ptr; type_key() { } type_key(key_type k, type * p) : key(k), ptr(p) { } }; template bool operator < (const type_key & a, const type_key & b) { return a.key < b.key; } template bool operator > (const type_key & a, const type_key & b) { return a.key > b.key; } template class bid_sequence { public: typedef BIDType_ bid_type; typedef bid_type & reference; typedef AllocStrategy_ alloc_strategy; typedef typename simple_vector::size_type size_type; typedef typename simple_vector::iterator iterator; protected: simple_vector * bids; alloc_strategy alloc_strategy_; public: bid_sequence() { } bid_sequence(size_type size_) { bids = new simple_vector(size_); block_manager * mng = block_manager::get_instance(); mng->new_blocks(alloc_strategy_, bids->begin(), bids->end()); } void init(size_type size_) { bids = new simple_vector(size_); block_manager * mng = block_manager::get_instance(); mng->new_blocks(alloc_strategy_, bids->begin(), bids->end()); } reference operator [] (size_type i) { size_type size_ = size(); // cache size in a register if (i < size_) return *(bids->begin() + i); block_manager * mng = block_manager::get_instance(); simple_vector * larger_bids = new simple_vector((i + 1) * 2); std::copy(bids->begin(), bids->end(), larger_bids->begin()); mng->new_blocks(alloc_strategy_, larger_bids->begin() + size_, larger_bids->end()); delete bids; bids = larger_bids; return *(larger_bids->begin() + i); } size_type size() { return bids->size(); } iterator begin() { return bids->begin(); } ~bid_sequence() { block_manager::get_instance()->delete_blocks(bids->begin(), bids->end()); delete bids; } }; template void distribute( bid_sequence * bucket_bids, int64 * bucket_sizes, const int_type nbuckets, const int_type lognbuckets, ExtIterator_ first, ExtIterator_ last, const int_type nread_buffers, const int_type nwrite_buffers) { typedef typename ExtIterator_::vector_type::value_type value_type; typedef typename value_type::key_type key_type; typedef typename ExtIterator_::block_type block_type; typedef typename block_type::bid_type bid_type; typedef buf_istream buf_istream_type; int_type i = 0; buf_istream_type in(first.bid(), last.bid() + ((first.block_offset()) ? 1 : 0), nread_buffers); buffered_writer out( nbuckets + nwrite_buffers, nwrite_buffers); unsigned_type * bucket_block_offsets = new unsigned_type[nbuckets]; unsigned_type * bucket_iblock = new unsigned_type[nbuckets]; block_type ** bucket_blocks = new block_type *[nbuckets]; std::fill(bucket_sizes, bucket_sizes + nbuckets, 0); std::fill(bucket_iblock, bucket_iblock + nbuckets, 0); std::fill(bucket_block_offsets, bucket_block_offsets + nbuckets, 0); for (i = 0; i < nbuckets; i++) bucket_blocks[i] = out.get_free_block(); ExtIterator_ cur = first - first.block_offset(); // skip part of the block before first untouched for ( ; cur != first; cur++) ++in; const int_type shift = sizeof(key_type) * 8 - lognbuckets; // search in the the range [_begin,_end) STXXL_VERBOSE_STABLE_KSORT("Shift by: " << shift << " bits, lognbuckets: " << lognbuckets); for ( ; cur != last; cur++) { key_type cur_key = in.current().key(); int_type ibucket = cur_key >> shift; int_type block_offset = bucket_block_offsets[ibucket]; in >> (bucket_blocks[ibucket]->elem[block_offset++]); if (block_offset == block_type::size) { block_offset = 0; int_type iblock = bucket_iblock[ibucket]++; bucket_blocks[ibucket] = out.write(bucket_blocks[ibucket], bucket_bids[ibucket][iblock]); } bucket_block_offsets[ibucket] = block_offset; } for (i = 0; i < nbuckets; i++) { if (bucket_block_offsets[i]) { out.write(bucket_blocks[i], bucket_bids[i][bucket_iblock[i]]); } bucket_sizes[i] = int64(block_type::size) * bucket_iblock[i] + bucket_block_offsets[i]; STXXL_VERBOSE_STABLE_KSORT("Bucket " << i << " has size " << bucket_sizes[i] << ", estimated size: " << ((last - first) / int64(nbuckets))); } delete[] bucket_blocks; delete[] bucket_block_offsets; delete[] bucket_iblock; } } //! \brief Sort records with integer keys //! \param first object of model of \c ext_random_access_iterator concept //! \param last object of model of \c ext_random_access_iterator concept //! \param M amount of memory for internal use (in bytes) //! \remark Elements must provide a method key() which returns the integer key. //! \remark Not yet fully implemented, it assumes that the keys are uniformly //! distributed between [0,(std::numeric_limits::max)(). template void stable_ksort(ExtIterator_ first, ExtIterator_ last, unsigned_type M) { STXXL_MSG("Warning: stable_ksort is not yet fully implemented, it assumes that the keys are uniformly distributed between [0,(std::numeric_limits::max)()]"); typedef typename ExtIterator_::vector_type::value_type value_type; typedef typename value_type::key_type key_type; typedef typename ExtIterator_::block_type block_type; typedef typename block_type::bid_type bid_type; typedef typename ExtIterator_::vector_type::alloc_strategy_type alloc_strategy; typedef stable_ksort_local::bid_sequence bucket_bids_type; typedef stable_ksort_local::type_key type_key_; first.flush(); // flush container double begin = timestamp(); unsigned_type i = 0; config * cfg = config::get_instance(); const unsigned_type m = M / block_type::raw_size; assert(2 * block_type::raw_size <= M); const unsigned_type write_buffers_multiple = 2; const unsigned_type read_buffers_multiple = 2; const unsigned_type ndisks = cfg->disks_number(); const unsigned_type min_num_read_write_buffers = (write_buffers_multiple + read_buffers_multiple) * ndisks; const unsigned_type nmaxbuckets = m - min_num_read_write_buffers; const unsigned_type lognbuckets = log2_floor(nmaxbuckets); const unsigned_type nbuckets = 1 << lognbuckets; const unsigned_type est_bucket_size = div_ceil((last - first) / nbuckets, block_type::size); //in blocks if (m < min_num_read_write_buffers + 2 || nbuckets < 2) { STXXL_ERRMSG("stxxl::stable_ksort: Not enough memory. Blocks available: " << m << ", required for r/w buffers: " << min_num_read_write_buffers << ", required for buckets: 2, nbuckets: " << nbuckets); throw bad_parameter("stxxl::stable_ksort(): INSUFFICIENT MEMORY provided, please increase parameter 'M'"); } STXXL_VERBOSE_STABLE_KSORT("Elements to sort: " << (last - first)); STXXL_VERBOSE_STABLE_KSORT("Number of buckets has to be reduced from " << nmaxbuckets << " to " << nbuckets); const unsigned_type nread_buffers = (m - nbuckets) * read_buffers_multiple / (read_buffers_multiple + write_buffers_multiple); const unsigned_type nwrite_buffers = (m - nbuckets) * write_buffers_multiple / (read_buffers_multiple + write_buffers_multiple); STXXL_VERBOSE_STABLE_KSORT("Read buffers in distribution phase: " << nread_buffers); STXXL_VERBOSE_STABLE_KSORT("Write buffers in distribution phase: " << nwrite_buffers); bucket_bids_type * bucket_bids = new bucket_bids_type[nbuckets]; for (i = 0; i < nbuckets; ++i) bucket_bids[i].init(est_bucket_size); int64 * bucket_sizes = new int64[nbuckets]; disk_queues::get_instance()->set_priority_op(request_queue::WRITE); stable_ksort_local::distribute( bucket_bids, bucket_sizes, nbuckets, lognbuckets, first, last, nread_buffers, nwrite_buffers); double dist_end = timestamp(), end; double io_wait_after_d = stats::get_instance()->get_io_wait_time(); { // sort buckets unsigned_type write_buffers_multiple_bs = 2; unsigned_type max_bucket_size_bl = (m - write_buffers_multiple_bs * ndisks) / 2; // in number of blocks int64 max_bucket_size_rec = int64(max_bucket_size_bl) * block_type::size; // in number of records int64 max_bucket_size_act = 0; // actual max bucket size // establish output stream for (i = 0; i < nbuckets; i++) { max_bucket_size_act = STXXL_MAX(bucket_sizes[i], max_bucket_size_act); if (bucket_sizes[i] > max_bucket_size_rec) { STXXL_ERRMSG("Bucket " << i << " is too large: " << bucket_sizes[i] << " records, maximum: " << max_bucket_size_rec); STXXL_ERRMSG("Recursion on buckets is not yet implemented, aborting."); abort(); } } // here we can increase write_buffers_multiple_b knowing max(bucket_sizes[i]) // ... and decrease max_bucket_size_bl const int_type max_bucket_size_act_bl = div_ceil(max_bucket_size_act, block_type::size); STXXL_VERBOSE_STABLE_KSORT("Reducing required number of required blocks per bucket from " << max_bucket_size_bl << " to " << max_bucket_size_act_bl); max_bucket_size_rec = max_bucket_size_act; max_bucket_size_bl = max_bucket_size_act_bl; const unsigned_type nwrite_buffers_bs = m - 2 * max_bucket_size_bl; STXXL_VERBOSE_STABLE_KSORT("Write buffers in bucket sorting phase: " << nwrite_buffers_bs); typedef buf_ostream buf_ostream_type; buf_ostream_type out(first.bid(), nwrite_buffers_bs); disk_queues::get_instance()->set_priority_op(request_queue::READ); if (first.block_offset()) { // has to skip part of the first block block_type * block = new block_type; request_ptr req; req = block->read(*first.bid()); req->wait(); for (i = 0; i < first.block_offset(); i++) { out << block->elem[i]; } delete block; } block_type * blocks1 = new block_type[max_bucket_size_bl]; block_type * blocks2 = new block_type[max_bucket_size_bl]; request_ptr * reqs1 = new request_ptr[max_bucket_size_bl]; request_ptr * reqs2 = new request_ptr[max_bucket_size_bl]; type_key_ * refs1 = new type_key_[max_bucket_size_rec]; type_key_ * refs2 = new type_key_[max_bucket_size_rec]; // submit reading first 2 buckets (Peter's scheme) unsigned_type nbucket_blocks = div_ceil(bucket_sizes[0], block_type::size); for (i = 0; i < nbucket_blocks; i++) reqs1[i] = blocks1[i].read(bucket_bids[0][i]); nbucket_blocks = div_ceil(bucket_sizes[1], block_type::size); for (i = 0; i < nbucket_blocks; i++) reqs2[i] = blocks2[i].read(bucket_bids[1][i]); key_type offset = 0; const unsigned log_k1 = STXXL_MAX(log2_ceil(max_bucket_size_rec * sizeof(type_key_) / STXXL_L2_SIZE), 1); unsigned_type k1 = 1 << log_k1; int_type * bucket1 = new int_type[k1]; const unsigned shift = sizeof(key_type) * 8 - lognbuckets; const unsigned shift1 = shift - log_k1; STXXL_VERBOSE_STABLE_KSORT("Classifying " << nbuckets << " buckets, max size:" << max_bucket_size_rec << " block size:" << block_type::size << " log_k1:" << log_k1); for (unsigned_type k = 0; k < nbuckets; k++) { nbucket_blocks = div_ceil(bucket_sizes[k], block_type::size); const unsigned log_k1_k = STXXL_MAX(log2_ceil(bucket_sizes[k] * sizeof(type_key_) / STXXL_L2_SIZE), 1); assert(log_k1_k <= log_k1); k1 = 1 << log_k1_k; std::fill(bucket1, bucket1 + k1, 0); STXXL_VERBOSE_STABLE_KSORT("Classifying bucket " << k << " size:" << bucket_sizes[k] << " blocks:" << nbucket_blocks << " log_k1:" << log_k1_k); // classify first nbucket_blocks-1 blocks, they are full type_key_ * ref_ptr = refs1; key_type offset1 = offset + (key_type(1) << key_type(shift)) * key_type(k); for (i = 0; i < nbucket_blocks - 1; i++) { reqs1[i]->wait(); stable_ksort_local::classify_block(blocks1[i].begin(), blocks1[i].end(), ref_ptr, bucket1, offset1, shift1 /*,k1*/); } // last block might be non-full const unsigned_type last_block_size = bucket_sizes[k] - int64(nbucket_blocks - 1) * block_type::size; reqs1[i]->wait(); //STXXL_MSG("block_type::size: "<ptr)); delete[] bucket2; c = cEnd; d = dEnd; } // submit next read const unsigned_type bucket2submit = k + 2; if (bucket2submit < nbuckets) { nbucket_blocks = div_ceil(bucket_sizes[bucket2submit], block_type::size); for (i = 0; i < nbucket_blocks; i++) reqs1[i] = blocks1[i].read(bucket_bids[bucket2submit][i]); } std::swap(blocks1, blocks2); std::swap(reqs1, reqs2); } delete[] bucket1; delete[] refs1; delete[] refs2; delete[] blocks1; delete[] blocks2; delete[] reqs1; delete[] reqs2; delete[] bucket_bids; delete[] bucket_sizes; if (last.block_offset()) { // has to skip part of the first block block_type * block = new block_type; request_ptr req = block->read(*last.bid()); req->wait(); for (i = last.block_offset(); i < block_type::size; i++) { out << block->elem[i]; } delete block; } end = timestamp(); } STXXL_VERBOSE("Elapsed time : " << end - begin << " s. Distribution time: " << dist_end - begin << " s"); STXXL_VERBOSE("Time in I/O wait(ds): " << io_wait_after_d << " s"); STXXL_VERBOSE(*stats::get_instance()); STXXL_UNUSED(begin + dist_end + end + io_wait_after_d); } //! \} __STXXL_END_NAMESPACE #endif // !STXXL_STABLE_KSORT_HEADER stxxl-1.3.1/include/stxxl/bits/algo/inmemsort.h0000644000175000017500000000411311535500414021365 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/algo/inmemsort.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2003 Roman Dementiev * Copyright (C) 2010 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_IN_MEMORY_SORT_HEADER #define STXXL_IN_MEMORY_SORT_HEADER #include #include #include #include #include #include #include __STXXL_BEGIN_NAMESPACE template void stl_in_memory_sort(ExtIterator_ first, ExtIterator_ last, StrictWeakOrdering_ cmp) { typedef typename ExtIterator_::vector_type::value_type value_type; typedef typename ExtIterator_::block_type block_type; STXXL_VERBOSE("stl_in_memory_sort, range: " << (last - first)); first.flush(); unsigned_type nblocks = last.bid() - first.bid() + (last.block_offset() ? 1 : 0); simple_vector blocks(nblocks); simple_vector reqs(nblocks); unsigned_type i; for (i = 0; i < nblocks; ++i) reqs[i] = blocks[i].read(*(first.bid() + i)); wait_all(reqs.begin(), nblocks); unsigned_type last_block_correction = last.block_offset() ? (block_type::size - last.block_offset()) : 0; potentially_parallel:: sort(make_element_iterator(blocks.begin(), first.block_offset()), make_element_iterator(blocks.begin(), nblocks * block_type::size - last_block_correction), cmp); for (i = 0; i < nblocks; ++i) reqs[i] = blocks[i].write(*(first.bid() + i)); wait_all(reqs.begin(), nblocks); } __STXXL_END_NAMESPACE #endif // !STXXL_IN_MEMORY_SORT_HEADER stxxl-1.3.1/include/stxxl/bits/algo/intksort.h0000644000175000017500000002154111520246314021231 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/algo/intksort.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2002 Peter Sanders * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_INTKSORT_HEADER #define STXXL_INTKSORT_HEADER #include #include #include #include #include __STXXL_BEGIN_NAMESPACE template static void count(type_key * a, type_key * aEnd, int_type * bucket, int_type K, typename type_key::key_type offset, unsigned shift) { // reset buckets std::fill(bucket, bucket + K, 0); // count occupancies for (type_key * p = a; p < aEnd; p++) { int_type i = (p->key - offset) >> shift; /* if (!(i < K && i >= 0)) { STXXL_ERRMSG("i: " << i); abort(); } */ bucket[i]++; } } static void exclusive_prefix_sum(int_type * bucket, int_type K) { int_type sum = 0; for (int_type i = 0; i < K; i++) { int_type current = bucket[i]; bucket[i] = sum; sum += current; } } // distribute input a to output b using bucket for the starting indices template static void classify(type_key * a, type_key * aEnd, type_key * b, int_type * bucket, typename type_key::key_type offset, unsigned shift) { for (type_key * p = a; p < aEnd; p++) { int_type i = (p->key - offset) >> shift; int_type bi = bucket[i]; b[bi] = *p; bucket[i] = bi + 1; } } template inline void sort2(T & a, T & b) { if (b < a) std::swap(a, b); } template inline void sort3(T & a, T & b, T & c) { T temp; if (b < a) { if (c < a) { // b , c < a if (b < c) { // b < c < a temp = a; a = b; b = c; c = temp; } else { // c <=b < a std::swap(c, a); } } else { // b < a <=c std::swap(a, b); } } else { // a <=b if (c < a) { // c < a <=b temp = a; a = c; c = b; b = temp; } else { // a <=b , c if (c < b) { // a <=c < b std::swap(b, c); } } } // Assert1 (!(b < a) && !(c < b)); } template inline void sort4(T & a, T & b, T & c, T & d) { sort2(a, b); sort2(c, d); // a < b ; c < d if (c < a) { // c minimal, a < b if (d < a) { // c < d < a < b std::swap(a, c); std::swap(b, d); } else { // c < a < {db} if (d < b) { // c < a < d < b T temp = a; a = c; c = d; d = b; b = temp; } else { // c < a < b < d T temp = a; a = c; c = b; b = temp; } } } else { // a minimal ; c < d if (c < b) { // c < (bd) if (d < b) { // c < d < b T temp = b; b = c; c = d; d = temp; } else { // a < c < b < d std::swap(b, c); } } // else sorted } //Assert1 (!(b < a) && !(c < b) & !(d < c)); } template inline void sort5(T & a, T & b, T & c, T & d, T & e) { sort2(a, b); sort2(d, e); if (d < a) { std::swap(a, d); std::swap(b, e); } // a < d < e, a < b if (d < c) { std::swap(c, d); // a minimal, c < {de} sort2(d, e); } else { // a inline void insertion_sort(T * a, T * aEnd) { T * pp; for (T * p = a + 1; p < aEnd; p++) { // Invariant a..p-1 is sorted; T t = *p; if (t < *a) { // new minimum // move stuff to the right for (pp = p; pp != a; pp--) { *pp = *(pp - 1); } *pp = t; } else { // now we can use *a as a sentinel for (pp = p; t < *(pp - 1); pp--) { *pp = *(pp - 1); } *pp = t; } } } // sort each bucket // bucket[i] is an index one off to the right from // the end of the i-th bucket template static void cleanup(T * b, int_type * bucket, int_type K) { T * c = b; for (int_type i = 0; i < K; i++) { T * cEnd = b + bucket[i]; switch (cEnd - c) { case 0: break; case 1: break; case 2: sort2(c[0], c[1]); break; case 3: sort3(c[0], c[1], c[2]); break; case 4: sort4(c[0], c[1], c[2], c[3]); break; case 5: #if 0 sort5(c[0], c[1], c[2], c[3], c[4]); break; #endif case 6: case 7: case 8: case 9: case 10: case 11: case 12: case 13: case 14: case 15: case 16: insertion_sort(c, cEnd); break; default: potentially_parallel:: sort(c, cEnd); } c = cEnd; } } // do a single level MDS radix sort // using bucket[0..K-1] as a counter array // and using (key(x) - offset) >> shift to index buckets. // and using (key(x) - offset) >> shift to index buckets. // the input comes from a..aEnd-1 // the output goes to b template void l1sort(type_key * a, type_key * aEnd, type_key * b, int_type * bucket, int_type K, typename type_key::key_type offset, int shift) { count(a, aEnd, bucket, K, offset, shift); exclusive_prefix_sum(bucket, K); classify(a, aEnd, b, bucket, offset, shift); cleanup(b, bucket, K); } template void classify_block(type * begin, type * end, type_key * & out, int_type * bucket, typename key_extractor::key_type offset, unsigned shift, key_extractor keyobj) { assert(shift < (sizeof(typename key_extractor::key_type) * 8 + 1)); for (type * p = begin; p < end; p++, out++) // count & create references { out->ptr = p; typename key_extractor::key_type key = keyobj(*p); int_type ibucket = (key - offset) >> shift; out->key = key; bucket[ibucket]++; } } template void classify_block(type * begin, type * end, type_key * & out, int_type * bucket, typename type::key_type offset, unsigned shift, const int_type K, key_extractor keyobj) { assert(shift < (sizeof(typename type::key_type) * 8 + 1)); for (type * p = begin; p < end; p++, out++) // count & create references { out->ptr = p; typename type::key_type key = keyobj(*p); int_type ibucket = (key - offset) >> shift; /* if (!(ibucket < K && ibucket >= 0)) { STXXL_ERRMSG("ibucket: " << ibucket << " K:" << K); abort(); } */ out->key = key; bucket[ibucket]++; } STXXL_UNUSED(K); } __STXXL_END_NAMESPACE #endif // !STXXL_INTKSORT_HEADER stxxl-1.3.1/include/stxxl/bits/algo/run_cursor.h0000644000175000017500000000613411535151017021557 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/algo/run_cursor.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2003 Roman Dementiev * Copyright (C) 2009 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_RUN_CURSOR_HEADER #define STXXL_RUN_CURSOR_HEADER #include #include __STXXL_BEGIN_NAMESPACE template struct run_cursor { unsigned_type pos; block_type * buffer; run_cursor() : pos(0), buffer(NULL) { } inline typename block_type::const_reference current() const { return (*buffer)[pos]; } inline void operator ++ () { ++pos; } }; #ifdef STXXL_SORT_SINGLE_PREFETCHER template struct have_prefetcher { static void * untyped_prefetcher; }; #endif template struct run_cursor2 : public run_cursor #ifdef STXXL_SORT_SINGLE_PREFETCHER , public have_prefetcher<> #endif { typedef prefetcher_type_ prefetcher_type; typedef run_cursor2 _Self; typedef typename block_type::value_type value_type; using run_cursor::pos; using run_cursor::buffer; #ifdef STXXL_SORT_SINGLE_PREFETCHER static prefetcher_type * const prefetcher() // sorry, a hack { return reinterpret_cast(untyped_prefetcher); } static void set_prefetcher(prefetcher_type * pfptr) { untyped_prefetcher = pfptr; } run_cursor2() { } #else prefetcher_type * prefetcher_; prefetcher_type * & prefetcher() // sorry, a hack { return prefetcher_; } run_cursor2() { } run_cursor2(prefetcher_type * p) : prefetcher_(p) { } #endif inline bool empty() const { return (pos >= block_type::size); } inline void operator ++ (); inline void make_inf() { pos = block_type::size; } }; #ifdef STXXL_SORT_SINGLE_PREFETCHER template void * have_prefetcher::untyped_prefetcher = NULL; #endif template void run_cursor2::operator ++ () { assert(!empty()); ++pos; if (UNLIKELY(pos >= block_type::size)) { if (prefetcher()->block_consumed(buffer)) pos = 0; } } #if 0 template struct run_cursor_cmp { typedef run_cursor cursor_type; inline bool operator () (const cursor_type & a, const cursor_type & b) // greater or equal { return !((*a.buffer)[a.pos] < (*b.buffer)[b.pos]); } }; #endif __STXXL_END_NAMESPACE #endif // !STXXL_RUN_CURSOR_HEADER // vim: et:ts=4:sw=4 stxxl-1.3.1/include/stxxl/bits/algo/sort_base.h0000644000175000017500000000257011437171771021351 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/algo/sort_base.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2009 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_SORT_BASE_HEADER #define STXXL_SORT_BASE_HEADER #include #include #ifndef STXXL_NO_WARN_RECURSIVE_SORT #define STXXL_WARNMSG_RECURSIVE_SORT STXXL_ERRMSG #else #define STXXL_WARNMSG_RECURSIVE_SORT STXXL_VERBOSE #endif #ifndef STXXL_SORT_OPTIMAL_PREFETCHING #define STXXL_SORT_OPTIMAL_PREFETCHING 1 #endif #ifndef STXXL_CHECK_ORDER_IN_SORTS #define STXXL_CHECK_ORDER_IN_SORTS 0 #endif #ifndef STXXL_L2_SIZE #define STXXL_L2_SIZE (512 * 1024) #endif __STXXL_BEGIN_NAMESPACE // Optimal merging: merge r = pow(nruns,1/ceil(log(nruns)/log(m))) runs at once inline unsigned_type optimal_merge_factor(unsigned_type num_runs, unsigned_type max_concurrent_runs) { return unsigned_type(ceil(pow(num_runs, 1. / ceil(log(double(num_runs)) / log(double(max_concurrent_runs)))))); } __STXXL_END_NAMESPACE #endif // !STXXL_SORT_BASE_HEADER // vim: et:ts=4:sw=4 stxxl-1.3.1/include/stxxl/bits/algo/ksort.h0000644000175000017500000011567211536214454020536 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/algo/ksort.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2002 Roman Dementiev * Copyright (C) 2008-2011 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_KSORT_HEADER #define STXXL_KSORT_HEADER #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include //#define INTERLEAVED_ALLOC #define OPT_MERGING __STXXL_BEGIN_NAMESPACE //! \weakgroup stllayer STL-user layer //! Layer which groups STL compatible algorithms and containers //! \weakgroup stlalgo Algorithms //! \ingroup stllayer //! Algorithms with STL-compatible interface //! \{ /*! \internal */ namespace ksort_local { template struct trigger_entry { typedef _BIDTp bid_type; typedef _KeyTp key_type; bid_type bid; key_type key; operator bid_type () { return bid; } }; template inline bool operator < (const trigger_entry<_BIDTp, _KeyTp> & a, const trigger_entry<_BIDTp, _KeyTp> & b) { return (a.key < b.key); } template inline bool operator > (const trigger_entry<_BIDTp, _KeyTp> & a, const trigger_entry<_BIDTp, _KeyTp> & b) { return (a.key > b.key); } template struct type_key { typedef key_type1 key_type; key_type key; type * ptr; type_key() { } type_key(key_type k, type * p) : key(k), ptr(p) { } }; template bool operator < (const type_key & a, const type_key & b) { return a.key < b.key; } template bool operator > (const type_key & a, const type_key & b) { return a.key > b.key; } template struct write_completion_handler { block_type * block; bid_type bid; request_ptr * req; void operator () (request * /*completed_req*/) { * req = block->read(bid); } }; template inline void write_out( type_key_ * begin, type_key_ * end, block_type * & cur_blk, const block_type * end_blk, int_type & out_block, int_type & out_pos, run_type & run, write_completion_handler * & next_read, typename block_type::bid_type * & bids, request_ptr * write_reqs, request_ptr * read_reqs, input_bid_iterator & it, key_extractor keyobj) { typedef typename block_type::bid_type bid_type; typedef typename block_type::type type; type * elem = cur_blk->elem; for (type_key_ * p = begin; p < end; p++) { elem[out_pos++] = *(p->ptr); if (out_pos >= block_type::size) { run[out_block].key = keyobj(*(cur_blk->elem)); if (cur_blk < end_blk) { next_read->block = cur_blk; next_read->req = read_reqs + out_block; read_reqs[out_block] = NULL; bids[out_block] = next_read->bid = *(it++); write_reqs[out_block] = cur_blk->write( run[out_block].bid, // postpone read of block from next run // after write of block from this run *(next_read++)); } else { write_reqs[out_block] = cur_blk->write(run[out_block].bid); } cur_blk++; elem = cur_blk->elem; out_block++; out_pos = 0; } } } template < typename block_type, typename run_type, typename input_bid_iterator, typename key_extractor> void create_runs( input_bid_iterator it, run_type ** runs, const unsigned_type nruns, const unsigned_type m2, key_extractor keyobj) { typedef typename block_type::value_type type; typedef typename block_type::bid_type bid_type; typedef typename key_extractor::key_type key_type; typedef type_key type_key_; block_manager * bm = block_manager::get_instance(); block_type * Blocks1 = new block_type[m2]; block_type * Blocks2 = new block_type[m2]; bid_type * bids = new bid_type[m2]; type_key_ * refs1 = new type_key_[m2 * Blocks1->size]; type_key_ * refs2 = new type_key_[m2 * Blocks1->size]; request_ptr * read_reqs = new request_ptr[m2]; request_ptr * write_reqs = new request_ptr[m2]; write_completion_handler * next_run_reads = new write_completion_handler[m2]; run_type * run; run = *runs; int_type run_size = (*runs)->size(); key_type offset = 0; const int log_k1 = log2_ceil((m2 * block_type::size * sizeof(type_key_) / STXXL_L2_SIZE) ? (m2 * block_type::size * sizeof(type_key_) / STXXL_L2_SIZE) : 2); const int log_k2 = log2_floor(m2 * Blocks1->size) - log_k1 - 1; STXXL_VERBOSE("log_k1: " << log_k1 << " log_k2:" << log_k2); const int_type k1 = 1 << log_k1; const int_type k2 = 1 << log_k2; int_type * bucket1 = new int_type[k1]; int_type * bucket2 = new int_type[k2]; int_type i; disk_queues::get_instance()->set_priority_op(request_queue::WRITE); for (i = 0; i < run_size; i++) { bids[i] = *(it++); read_reqs[i] = Blocks1[i].read(bids[i]); } unsigned_type k = 0; const int shift1 = sizeof(key_type) * 8 - log_k1; const int shift2 = shift1 - log_k2; STXXL_VERBOSE("shift1: " << shift1 << " shift2:" << shift2); for ( ; k < nruns; k++) { run = runs[k]; run_size = run->size(); std::fill(bucket1, bucket1 + k1, 0); type_key_ * ref_ptr = refs1; for (i = 0; i < run_size; i++) { if (k) write_reqs[i]->wait(); read_reqs[i]->wait(); bm->delete_block(bids[i]); classify_block(Blocks1[i].begin(), Blocks1[i].end(), ref_ptr, bucket1, offset, shift1, keyobj); } exclusive_prefix_sum(bucket1, k1); classify(refs1, refs1 + run_size * Blocks1->size, refs2, bucket1, offset, shift1); int_type out_block = 0; int_type out_pos = 0; unsigned_type next_run_size = (k < nruns - 1) ? (runs[k + 1]->size()) : 0; // recurse on each bucket type_key_ * c = refs2; type_key_ * d = refs1; block_type * cur_blk = Blocks2; block_type * end_blk = Blocks2 + next_run_size; write_completion_handler * next_read = next_run_reads; for (i = 0; i < k1; i++) { type_key_ * cEnd = refs2 + bucket1[i]; type_key_ * dEnd = refs1 + bucket1[i]; l1sort(c, cEnd, d, bucket2, k2, offset + (key_type(1) << key_type(shift1)) * key_type(i), shift2); // key_type,key_type,... paranoia write_out( d, dEnd, cur_blk, end_blk, out_block, out_pos, *run, next_read, bids, write_reqs, read_reqs, it, keyobj); c = cEnd; d = dEnd; } std::swap(Blocks1, Blocks2); } wait_all(write_reqs, m2); delete[] bucket1; delete[] bucket2; delete[] refs1; delete[] refs2; delete[] Blocks1; delete[] Blocks2; delete[] bids; delete[] next_run_reads; delete[] read_reqs; delete[] write_reqs; } template struct run_cursor2_cmp : public std::binary_function, run_cursor2, bool> { typedef run_cursor2 cursor_type; key_extractor keyobj; run_cursor2_cmp(key_extractor keyobj_) { keyobj = keyobj_; } inline bool operator () (const cursor_type & a, const cursor_type & b) const { if (UNLIKELY(b.empty())) return true; // sentinel emulation if (UNLIKELY(a.empty())) return false; //sentinel emulation return (keyobj(a.current()) < keyobj(b.current())); } private: run_cursor2_cmp() { } }; template class key_comparison : public std::binary_function { key_extractor ke; public: key_comparison() { } key_comparison(key_extractor ke_) : ke(ke_) { } bool operator () (const record_type & a, const record_type & b) const { return ke(a) < ke(b); } }; template bool check_ksorted_runs(run_type ** runs, unsigned_type nruns, unsigned_type m, key_ext_ keyext) { typedef typename block_type::value_type value_type; STXXL_MSG("check_ksorted_runs Runs: " << nruns); unsigned_type irun = 0; for (irun = 0; irun < nruns; ++irun) { const unsigned_type nblocks_per_run = runs[irun]->size(); unsigned_type blocks_left = nblocks_per_run; block_type * blocks = new block_type[m]; request_ptr * reqs = new request_ptr[m]; value_type last = keyext.min_value(); for (unsigned_type off = 0; off < nblocks_per_run; off += m) { const unsigned_type nblocks = STXXL_MIN(blocks_left, m); const unsigned_type nelements = nblocks * block_type::size; blocks_left -= nblocks; for (unsigned_type j = 0; j < nblocks; ++j) { reqs[j] = blocks[j].read((*runs[irun])[off + j].bid); } wait_all(reqs, reqs + nblocks); if (off && (keyext(blocks[0][0]) < keyext(last))) { STXXL_MSG("check_sorted_runs wrong first value in the run " << irun); STXXL_MSG(" first value: " << blocks[0][0] << " with key" << keyext(blocks[0][0])); STXXL_MSG(" last value: " << last << " with key" << keyext(last)); for (unsigned_type k = 0; k < block_type::size; ++k) STXXL_MSG("Element " << k << " in the block is :" << blocks[0][k] << " key: " << keyext(blocks[0][k])); return false; } for (unsigned_type j = 0; j < nblocks; ++j) { if (keyext(blocks[j][0]) != (*runs[irun])[off + j].key) { STXXL_MSG("check_sorted_runs wrong trigger in the run " << irun << " block " << (off + j)); STXXL_MSG(" trigger value: " << (*runs[irun])[off + j].key); STXXL_MSG("Data in the block:"); for (unsigned_type k = 0; k < block_type::size; ++k) STXXL_MSG("Element " << k << " in the block is :" << blocks[j][k] << " with key: " << keyext(blocks[j][k])); STXXL_MSG("BIDS:"); for (unsigned_type k = 0; k < nblocks; ++k) { if (k == j) STXXL_MSG("Bad one comes next."); STXXL_MSG("BID " << (off + k) << " is: " << ((*runs[irun])[off + k].bid)); } return false; } } if (!stxxl::is_sorted(make_element_iterator(blocks, 0), make_element_iterator(blocks, nelements), key_comparison())) { STXXL_MSG("check_sorted_runs wrong order in the run " << irun); STXXL_MSG("Data in blocks:"); for (unsigned_type j = 0; j < nblocks; ++j) { for (unsigned_type k = 0; k < block_type::size; ++k) STXXL_MSG(" Element " << k << " in block " << (off + j) << " is :" << blocks[j][k] << " with key: " << keyext(blocks[j][k])); } STXXL_MSG("BIDS:"); for (unsigned_type k = 0; k < nblocks; ++k) { STXXL_MSG("BID " << (k + off) << " is: " << ((*runs[irun])[k + off].bid)); } return false; } last = blocks[nblocks - 1][block_type::size - 1]; } assert(blocks_left == 0); delete[] reqs; delete[] blocks; } return true; } template void merge_runs(run_type ** in_runs, unsigned_type nruns, run_type * out_run, unsigned_type _m, key_extractor keyobj) { typedef block_prefetcher prefetcher_type; typedef run_cursor2 run_cursor_type; unsigned_type i; run_type consume_seq(out_run->size()); int_type * prefetch_seq = new int_type[out_run->size()]; typename run_type::iterator copy_start = consume_seq.begin(); for (i = 0; i < nruns; i++) { // TODO: try to avoid copy copy_start = std::copy( in_runs[i]->begin(), in_runs[i]->end(), copy_start); } std::stable_sort(consume_seq.begin(), consume_seq.end() _STXXL_SORT_TRIGGER_FORCE_SEQUENTIAL); unsigned disks_number = config::get_instance()->disks_number(); #ifdef PLAY_WITH_OPT_PREF const int_type n_write_buffers = 4 * disks_number; #else const int_type n_prefetch_buffers = STXXL_MAX(int_type(2 * disks_number), (3 * (int_type(_m) - int_type(nruns)) / 4)); STXXL_VERBOSE("Prefetch buffers " << n_prefetch_buffers); const int_type n_write_buffers = STXXL_MAX(int_type(2 * disks_number), int_type(_m) - int_type(nruns) - int_type(n_prefetch_buffers)); STXXL_VERBOSE("Write buffers " << n_write_buffers); // heuristic const int_type n_opt_prefetch_buffers = 2 * int_type(disks_number) + (3 * (int_type(n_prefetch_buffers) - int_type(2 * disks_number))) / 10; STXXL_VERBOSE("Prefetch buffers " << n_opt_prefetch_buffers); #endif #if STXXL_SORT_OPTIMAL_PREFETCHING compute_prefetch_schedule( consume_seq, prefetch_seq, n_opt_prefetch_buffers, disks_number); #else for (i = 0; i < out_run->size(); i++) prefetch_seq[i] = i; #endif prefetcher_type prefetcher(consume_seq.begin(), consume_seq.end(), prefetch_seq, nruns + n_prefetch_buffers); buffered_writer writer(n_write_buffers, n_write_buffers / 2); unsigned_type out_run_size = out_run->size(); run_cursor2_cmp cmp(keyobj); loser_tree< run_cursor_type, run_cursor2_cmp > losers(&prefetcher, nruns, cmp); block_type * out_buffer = writer.get_free_block(); for (i = 0; i < out_run_size; i++) { losers.multi_merge(out_buffer->elem, out_buffer->elem + block_type::size); (*out_run)[i].key = keyobj(out_buffer->elem[0]); out_buffer = writer.write(out_buffer, (*out_run)[i].bid); } delete[] prefetch_seq; block_manager * bm = block_manager::get_instance(); for (i = 0; i < nruns; i++) { unsigned_type sz = in_runs[i]->size(); for (unsigned_type j = 0; j < sz; j++) bm->delete_block((*in_runs[i])[j].bid); delete in_runs[i]; } } template simple_vector > * ksort_blocks(input_bid_iterator input_bids, unsigned_type _n, unsigned_type _m, key_extractor keyobj) { typedef typename block_type::value_type type; typedef typename key_extractor::key_type key_type; typedef typename block_type::bid_type bid_type; typedef trigger_entry trigger_entry_type; typedef simple_vector run_type; typedef typename interleaved_alloc_traits::strategy interleaved_alloc_strategy; unsigned_type m2 = div_ceil(_m, 2); const unsigned_type m2_rf = m2 * block_type::raw_size / (block_type::raw_size + block_type::size * sizeof(type_key)); STXXL_VERBOSE("Reducing number of blocks in a run from " << m2 << " to " << m2_rf << " due to key size: " << sizeof(typename key_extractor::key_type) << " bytes"); m2 = m2_rf; unsigned_type full_runs = _n / m2; unsigned_type partial_runs = ((_n % m2) ? 1 : 0); unsigned_type nruns = full_runs + partial_runs; unsigned_type i; block_manager * mng = block_manager::get_instance(); STXXL_VERBOSE("n=" << _n << " nruns=" << nruns << "=" << full_runs << "+" << partial_runs); double begin = timestamp(), after_runs_creation, end; run_type ** runs = new run_type *[nruns]; for (i = 0; i < full_runs; i++) runs[i] = new run_type(m2); #ifdef INTERLEAVED_ALLOC if (partial_runs) { unsigned_type last_run_size = _n - full_runs * m2; runs[i] = new run_type(last_run_size); mng->new_blocks(interleaved_alloc_strategy(nruns, alloc_strategy()), RunsToBIDArrayAdaptor2 (runs, 0, nruns, last_run_size), RunsToBIDArrayAdaptor2 (runs, _n, nruns, last_run_size)); } else mng->new_blocks(interleaved_alloc_strategy(nruns, alloc_strategy()), RunsToBIDArrayAdaptor (runs, 0, nruns), RunsToBIDArrayAdaptor (runs, _n, nruns)); #else if (partial_runs) runs[i] = new run_type(_n - full_runs * m2); for (i = 0; i < nruns; i++) { mng->new_blocks(alloc_strategy(), make_bid_iterator(runs[i]->begin()), make_bid_iterator(runs[i]->end())); } #endif create_runs(input_bids, runs, nruns, m2, keyobj); after_runs_creation = timestamp(); double io_wait_after_rf = stats::get_instance()->get_io_wait_time(); disk_queues::get_instance()->set_priority_op(request_queue::WRITE); const int_type merge_factor = optimal_merge_factor(nruns, _m); run_type ** new_runs; while (nruns > 1) { int_type new_nruns = div_ceil(nruns, merge_factor); STXXL_VERBOSE("Starting new merge phase: nruns: " << nruns << " opt_merge_factor: " << merge_factor << " m:" << _m << " new_nruns: " << new_nruns); new_runs = new run_type *[new_nruns]; int_type runs_left = nruns; int_type cur_out_run = 0; int_type blocks_in_new_run = 0; while (runs_left > 0) { int_type runs2merge = STXXL_MIN(runs_left, merge_factor); blocks_in_new_run = 0; for (unsigned_type i = nruns - runs_left; i < (nruns - runs_left + runs2merge); i++) blocks_in_new_run += runs[i]->size(); // allocate run new_runs[cur_out_run++] = new run_type(blocks_in_new_run); runs_left -= runs2merge; } // allocate blocks in the new runs if (cur_out_run == 1 && blocks_in_new_run == int_type(_n) && !input_bids->is_managed()) { // if we sort a file we can reuse the input bids for the output input_bid_iterator cur = input_bids; for (int_type i = 0; cur != (input_bids + _n); ++cur) { (*new_runs[0])[i++].bid = *cur; } bid_type & firstBID = (*new_runs[0])[0].bid; if (firstBID.is_managed()) { // the first block does not belong to the file // need to reallocate it mng->new_block(FR(), firstBID); } bid_type & lastBID = (*new_runs[0])[_n - 1].bid; if (lastBID.is_managed()) { // the first block does not belong to the file // need to reallocate it mng->new_block(FR(), lastBID); } } else { mng->new_blocks(interleaved_alloc_strategy(new_nruns, alloc_strategy()), RunsToBIDArrayAdaptor2(new_runs, 0, new_nruns, blocks_in_new_run), RunsToBIDArrayAdaptor2(new_runs, _n, new_nruns, blocks_in_new_run)); } // merge all runs_left = nruns; cur_out_run = 0; while (runs_left > 0) { int_type runs2merge = STXXL_MIN(runs_left, merge_factor); #if STXXL_CHECK_ORDER_IN_SORTS assert((check_ksorted_runs(runs + nruns - runs_left, runs2merge, m2, keyobj))); #endif STXXL_VERBOSE("Merging " << runs2merge << " runs"); merge_runs(runs + nruns - runs_left, runs2merge, *(new_runs + (cur_out_run++)), _m, keyobj); runs_left -= runs2merge; } nruns = new_nruns; delete[] runs; runs = new_runs; } run_type * result = *runs; delete[] runs; end = timestamp(); STXXL_VERBOSE("Elapsed time : " << end - begin << " s. Run creation time: " << after_runs_creation - begin << " s"); STXXL_VERBOSE("Time in I/O wait(rf): " << io_wait_after_rf << " s"); STXXL_VERBOSE(*stats::get_instance()); STXXL_UNUSED(begin + after_runs_creation + end + io_wait_after_rf); return result; } } /*! \page key_extractor Key extractor concept Model of \b Key \b extractor concept must: - define type \b key_type , - provide \b operator() that returns key value of an object of user type - provide \b max_value method that returns a value that is \b strictly \b greater than all other objects of user type in respect to the key obtained by this key extractor , - provide \b min_value method that returns a value that is \b strictly \b less than all other objects of user type in respect to the key obtained by this key extractor , - operator > , operator <, operator == and operator != on type \b key_type must be defined. - \b Note: when using unsigned integral types as key, the value 0 cannot be used as a key value because it would conflict with the sentinel value returned by \b min_value Example: extractor class \b GetWeight, that extracts weight from an \b Edge \verbatim struct Edge { unsigned src,dest,weight; Edge(unsigned s,unsigned d,unsigned w):src(s),dest(d),weight(w){} }; struct GetWeight { typedef unsigned key_type; key_type operator() (const Edge & e) const { return e.weight; } Edge min_value() const { return Edge(0,0,(std::numeric_limits::min)()); }; Edge max_value() const { return Edge(0,0,(std::numeric_limits::max)()); }; }; \endverbatim */ //! \brief Sort records with integer keys //! \param first_ object of model of \c ext_random_access_iterator concept //! \param last_ object of model of \c ext_random_access_iterator concept //! \param keyobj \link key_extractor key extractor \endlink object //! \param M__ amount of memory for internal use (in bytes) //! \remark Order in the result is non-stable template void ksort(ExtIterator_ first_, ExtIterator_ last_, KeyExtractor_ keyobj, unsigned_type M__) { typedef simple_vector > run_type; typedef typename ExtIterator_::vector_type::value_type value_type; typedef typename ExtIterator_::block_type block_type; unsigned_type n = 0; block_manager * mng = block_manager::get_instance(); first_.flush(); if ((last_ - first_) * sizeof(value_type) < M__) { stl_in_memory_sort(first_, last_, ksort_local::key_comparison(keyobj)); } else { assert(2 * block_type::raw_size <= M__); if (first_.block_offset()) { if (last_.block_offset()) // first and last element reside // not in the beginning of the block { typename ExtIterator_::block_type * first_block = new typename ExtIterator_::block_type; typename ExtIterator_::block_type * last_block = new typename ExtIterator_::block_type; typename ExtIterator_::bid_type first_bid, last_bid; request_ptr req; req = first_block->read(*first_.bid()); mng->new_block(FR(), first_bid); // try to overlap mng->new_block(FR(), last_bid); req->wait(); req = last_block->read(*last_.bid()); unsigned_type i = 0; for ( ; i < first_.block_offset(); i++) { first_block->elem[i] = keyobj.min_value(); } req->wait(); req = first_block->write(first_bid); for (i = last_.block_offset(); i < block_type::size; i++) { last_block->elem[i] = keyobj.max_value(); } req->wait(); req = last_block->write(last_bid); n = last_.bid() - first_.bid() + 1; std::swap(first_bid, *first_.bid()); std::swap(last_bid, *last_.bid()); req->wait(); delete first_block; delete last_block; run_type * out = ksort_local::ksort_blocks< typename ExtIterator_::block_type, typename ExtIterator_::vector_type::alloc_strategy_type, typename ExtIterator_::bids_container_iterator, KeyExtractor_> (first_.bid(), n, M__ / block_type::raw_size, keyobj); first_block = new typename ExtIterator_::block_type; last_block = new typename ExtIterator_::block_type; typename ExtIterator_::block_type * sorted_first_block = new typename ExtIterator_::block_type; typename ExtIterator_::block_type * sorted_last_block = new typename ExtIterator_::block_type; request_ptr * reqs = new request_ptr[2]; reqs[0] = first_block->read(first_bid); reqs[1] = sorted_first_block->read((*(out->begin())).bid); wait_all(reqs, 2); reqs[0] = last_block->read(last_bid); reqs[1] = sorted_last_block->read(((*out)[out->size() - 1]).bid); for (i = first_.block_offset(); i < block_type::size; i++) { first_block->elem[i] = sorted_first_block->elem[i]; } wait_all(reqs, 2); req = first_block->write(first_bid); for (i = 0; i < last_.block_offset(); i++) { last_block->elem[i] = sorted_last_block->elem[i]; } req->wait(); req = last_block->write(last_bid); mng->delete_block(out->begin()->bid); mng->delete_block((*out)[out->size() - 1].bid); *first_.bid() = first_bid; *last_.bid() = last_bid; typename run_type::iterator it = out->begin(); it++; typename ExtIterator_::bids_container_iterator cur_bid = first_.bid(); cur_bid++; for ( ; cur_bid != last_.bid(); cur_bid++, it++) { *cur_bid = (*it).bid; } delete first_block; delete sorted_first_block; delete sorted_last_block; delete[] reqs; delete out; req->wait(); delete last_block; } else { // first element resides // not in the beginning of the block typename ExtIterator_::block_type * first_block = new typename ExtIterator_::block_type; typename ExtIterator_::bid_type first_bid; request_ptr req; req = first_block->read(*first_.bid()); mng->new_block(FR(), first_bid); // try to overlap req->wait(); unsigned_type i = 0; for ( ; i < first_.block_offset(); i++) { first_block->elem[i] = keyobj.min_value(); } req = first_block->write(first_bid); n = last_.bid() - first_.bid(); std::swap(first_bid, *first_.bid()); req->wait(); delete first_block; run_type * out = ksort_local::ksort_blocks< typename ExtIterator_::block_type, typename ExtIterator_::vector_type::alloc_strategy_type, typename ExtIterator_::bids_container_iterator, KeyExtractor_> (first_.bid(), n, M__ / block_type::raw_size, keyobj); first_block = new typename ExtIterator_::block_type; typename ExtIterator_::block_type * sorted_first_block = new typename ExtIterator_::block_type; request_ptr * reqs = new request_ptr[2]; reqs[0] = first_block->read(first_bid); reqs[1] = sorted_first_block->read((*(out->begin())).bid); wait_all(reqs, 2); for (i = first_.block_offset(); i < block_type::size; i++) { first_block->elem[i] = sorted_first_block->elem[i]; } req = first_block->write(first_bid); mng->delete_block(out->begin()->bid); *first_.bid() = first_bid; typename run_type::iterator it = out->begin(); it++; typename ExtIterator_::bids_container_iterator cur_bid = first_.bid(); cur_bid++; for ( ; cur_bid != last_.bid(); cur_bid++, it++) { *cur_bid = (*it).bid; } *cur_bid = (*it).bid; delete sorted_first_block; delete[] reqs; delete out; req->wait(); delete first_block; } } else { if (last_.block_offset()) // last element resides // not in the beginning of the block { typename ExtIterator_::block_type * last_block = new typename ExtIterator_::block_type; typename ExtIterator_::bid_type last_bid; request_ptr req; unsigned_type i; req = last_block->read(*last_.bid()); mng->new_block(FR(), last_bid); req->wait(); for (i = last_.block_offset(); i < block_type::size; i++) { last_block->elem[i] = keyobj.max_value(); } req = last_block->write(last_bid); n = last_.bid() - first_.bid() + 1; std::swap(last_bid, *last_.bid()); req->wait(); delete last_block; run_type * out = ksort_local::ksort_blocks< typename ExtIterator_::block_type, typename ExtIterator_::vector_type::alloc_strategy_type, typename ExtIterator_::bids_container_iterator, KeyExtractor_> (first_.bid(), n, M__ / block_type::raw_size, keyobj); last_block = new typename ExtIterator_::block_type; typename ExtIterator_::block_type * sorted_last_block = new typename ExtIterator_::block_type; request_ptr * reqs = new request_ptr[2]; reqs[0] = last_block->read(last_bid); reqs[1] = sorted_last_block->read(((*out)[out->size() - 1]).bid); wait_all(reqs, 2); for (i = 0; i < last_.block_offset(); i++) { last_block->elem[i] = sorted_last_block->elem[i]; } req = last_block->write(last_bid); mng->delete_block((*out)[out->size() - 1].bid); *last_.bid() = last_bid; typename run_type::iterator it = out->begin(); typename ExtIterator_::bids_container_iterator cur_bid = first_.bid(); for ( ; cur_bid != last_.bid(); cur_bid++, it++) { *cur_bid = (*it).bid; } delete sorted_last_block; delete[] reqs; delete out; req->wait(); delete last_block; } else { // first and last element reside in the beginning of blocks n = last_.bid() - first_.bid(); run_type * out = ksort_local::ksort_blocks< typename ExtIterator_::block_type, typename ExtIterator_::vector_type::alloc_strategy_type, typename ExtIterator_::bids_container_iterator, KeyExtractor_> (first_.bid(), n, M__ / block_type::raw_size, keyobj); typename run_type::iterator it = out->begin(); typename ExtIterator_::bids_container_iterator cur_bid = first_.bid(); for ( ; cur_bid != last_.bid(); cur_bid++, it++) { *cur_bid = (*it).bid; } delete out; } } } #if STXXL_CHECK_ORDER_IN_SORTS typedef typename ExtIterator_::const_iterator const_iterator; assert(stxxl::is_sorted(const_iterator(first_), const_iterator(last_), ksort_local::key_comparison())); #endif } template struct ksort_defaultkey { typedef typename record_type::key_type key_type; key_type operator () (const record_type & obj) const { return obj.key(); } record_type max_value() const { return record_type::max_value(); } record_type min_value() const { return record_type::min_value(); } }; //! \brief Sort records with integer keys //! \param first_ object of model of \c ext_random_access_iterator concept //! \param last_ object of model of \c ext_random_access_iterator concept //! \param M__ amount of buffers for internal use //! \remark Order in the result is non-stable /*! Record's type must: - provide \b max_value method that returns an object that is \b greater than all other objects of user type , - provide \b min_value method that returns an object that is \b less than all other objects of user type , - \b operator \b < that must define strict weak ordering on record's values (see what it is). */ template void ksort(ExtIterator_ first_, ExtIterator_ last_, unsigned_type M__) { ksort(first_, last_, ksort_defaultkey(), M__); } //! \} __STXXL_END_NAMESPACE #endif // !STXXL_KSORT_HEADER // vim: et:ts=4:sw=4 stxxl-1.3.1/include/stxxl/bits/algo/losertree.h0000644000175000017500000001534611270250553021370 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/algo/losertree.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 1999 Peter Sanders * Copyright (C) 2002 Roman Dementiev * Copyright (C) 2009 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_LOSERTREE_HEADER #define STXXL_LOSERTREE_HEADER #include #include #include #include __STXXL_BEGIN_NAMESPACE template class loser_tree : private noncopyable { int logK; int_type k; int_type * entry; run_cursor_type * current; run_cursor_cmp_type cmp; int_type init_winner(int_type root) { if (root >= k) { return root - k; } else { int_type left = init_winner(2 * root); int_type right = init_winner(2 * root + 1); if (cmp(current[left], current[right])) { entry[root] = right; return left; } else { entry[root] = left; return right; } } } public: typedef typename run_cursor_type::prefetcher_type prefetcher_type; typedef typename run_cursor_type::value_type value_type; loser_tree( prefetcher_type * p, int_type nruns, run_cursor_cmp_type c) : cmp(c) { int_type i; logK = log2_ceil(nruns); int_type kReg = k = (1 << logK); STXXL_VERBOSE2("loser_tree: logK=" << logK << " nruns=" << nruns << " K=" << kReg); #ifdef STXXL_SORT_SINGLE_PREFETCHER current = new run_cursor_type[kReg]; run_cursor_type::set_prefetcher(p); #else current = new run_cursor_type[kReg]; for (i = 0; i < kReg; ++i) current[i].prefetcher() = p; #endif entry = new int_type[(kReg << 1)]; // init cursors for (i = 0; i < nruns; ++i) { current[i].buffer = p->pull_block(); //current[i].pos = 0; // done in constructor entry[kReg + i] = i; } for (i = nruns; i < kReg; ++i) { current[i].make_inf(); entry[kReg + i] = i; } entry[0] = init_winner(1); } ~loser_tree() { delete[] current; delete[] entry; } void swap(loser_tree & obj) { std::swap(logK, obj.logK); std::swap(k, obj.k); std::swap(entry, obj.entry); std::swap(current, obj.current); std::swap(cmp, obj.cmp); } private: template void multi_merge_unrolled(value_type * out_first, value_type * out_last) { run_cursor_type * currentE, * winnerE; int_type * regEntry = entry; int_type winnerIndex = regEntry[0]; while (LIKELY(out_first != out_last)) { winnerE = current + winnerIndex; *(out_first) = winnerE->current(); ++out_first; ++(*winnerE); #define TreeStep(L) \ if (LogK >= L) \ { \ currentE = current + \ regEntry[(winnerIndex + (1 << LogK)) >> (((int(LogK - L) + 1) >= 0) ? ((LogK - L) + 1) : 0)]; \ if (cmp(*currentE, *winnerE)) \ { \ std::swap(regEntry[(winnerIndex + (1 << LogK)) \ >> (((int(LogK - L) + 1) >= 0) ? ((LogK - L) + 1) : 0)], winnerIndex); \ winnerE = currentE; \ } \ } TreeStep(10); TreeStep(9); TreeStep(8); TreeStep(7); TreeStep(6); TreeStep(5); TreeStep(4); TreeStep(3); TreeStep(2); TreeStep(1); #undef TreeStep } regEntry[0] = winnerIndex; } void multi_merge_unrolled_0(value_type * out_first, value_type * out_last) { while (LIKELY(out_first != out_last)) { *out_first = current->current(); ++out_first; ++(*current); } } void multi_merge_k(value_type * out_first, value_type * out_last) { run_cursor_type * currentE, * winnerE; int_type kReg = k; int_type winnerIndex = entry[0]; while (LIKELY(out_first != out_last)) { winnerE = current + winnerIndex; *(out_first) = winnerE->current(); ++out_first; ++(*winnerE); for (int_type i = (winnerIndex + kReg) >> 1; i > 0; i >>= 1) { currentE = current + entry[i]; if (cmp(*currentE, *winnerE)) { std::swap(entry[i], winnerIndex); winnerE = currentE; } } } entry[0] = winnerIndex; } public: void multi_merge(value_type * out_first, value_type * out_last) { switch (logK) { case 0: multi_merge_unrolled_0(out_first, out_last); break; case 1: multi_merge_unrolled<1>(out_first, out_last); break; case 2: multi_merge_unrolled<2>(out_first, out_last); break; case 3: multi_merge_unrolled<3>(out_first, out_last); break; case 4: multi_merge_unrolled<4>(out_first, out_last); break; case 5: multi_merge_unrolled<5>(out_first, out_last); break; case 6: multi_merge_unrolled<6>(out_first, out_last); break; case 7: multi_merge_unrolled<7>(out_first, out_last); break; case 8: multi_merge_unrolled<8>(out_first, out_last); break; case 9: multi_merge_unrolled<9>(out_first, out_last); break; case 10: multi_merge_unrolled<10>(out_first, out_last); break; default: multi_merge_k(out_first, out_last); break; } } }; __STXXL_END_NAMESPACE namespace std { template void swap(stxxl::loser_tree & a, stxxl::loser_tree & b) { a.swap(b); } } #endif // !STXXL_LOSERTREE_HEADER // vim: et:ts=4:sw=4 stxxl-1.3.1/include/stxxl/bits/algo/scan.h0000644000175000017500000002063411535151017020303 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/algo/scan.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2002-2004 Roman Dementiev * Copyright (C) 2008, 2009 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_SCAN_HEADER #define STXXL_SCAN_HEADER #include #include #include __STXXL_BEGIN_NAMESPACE //! \addtogroup stlalgo //! \{ //! \brief External equivalent of std::for_each //! \remark The implementation exploits \c \ buffered streams (computation and I/O overlapped) //! \param _begin object of model of \c ext_random_access_iterator concept //! \param _end object of model of \c ext_random_access_iterator concept //! \param _functor function object of model of \c std::UnaryFunction concept //! \param nbuffers number of buffers (blocks) for internal use (should be at least 2*D ) //! \return function object \c _functor after it has been applied to the each element of the given range //! //! \warning nested stxxl::for_each are not supported template _UnaryFunction for_each(_ExtIterator _begin, _ExtIterator _end, _UnaryFunction _functor, int_type nbuffers) { if (_begin == _end) return _functor; typedef buf_istream buf_istream_type; _begin.flush(); // flush container // create prefetching stream, buf_istream_type in(_begin.bid(), _end.bid() + ((_end.block_offset()) ? 1 : 0), nbuffers); _ExtIterator _cur = _begin - _begin.block_offset(); // leave part of the block before _begin untouched (e.g. copy) for ( ; _cur != _begin; ++_cur) { typename _ExtIterator::value_type tmp; in >> tmp; } // apply _functor to the range [_begin,_end) for ( ; _cur != _end; ++_cur) { typename _ExtIterator::value_type tmp; in >> tmp; _functor(tmp); } // leave part of the block after _end untouched if (_end.block_offset()) { _ExtIterator _last_block_end = _end - _end.block_offset() + _ExtIterator::block_type::size; for ( ; _cur != _last_block_end; ++_cur) { typename _ExtIterator::value_type tmp; in >> tmp; } } return _functor; } //! \brief External equivalent of std::for_each (mutating) //! \remark The implementation exploits \c \ buffered streams (computation and I/O overlapped) //! \param _begin object of model of \c ext_random_access_iterator concept //! \param _end object of model of \c ext_random_access_iterator concept //! \param _functor //! \param nbuffers number of buffers (blocks) for internal use (should be at least 2*D ) //! \return function object \c _functor after it has been applied to the each element of the given range //! //! \warning nested stxxl::for_each_m are not supported template _UnaryFunction for_each_m(_ExtIterator _begin, _ExtIterator _end, _UnaryFunction _functor, int_type nbuffers) { if (_begin == _end) return _functor; typedef buf_istream buf_istream_type; typedef buf_ostream buf_ostream_type; _begin.flush(); // flush container // create prefetching stream, buf_istream_type in(_begin.bid(), _end.bid() + ((_end.block_offset()) ? 1 : 0), nbuffers / 2); // create buffered write stream for blocks buf_ostream_type out(_begin.bid(), nbuffers / 2); // REMARK: these two streams do I/O while // _functor is being computed (overlapping for free) _ExtIterator _cur = _begin - _begin.block_offset(); // leave part of the block before _begin untouched (e.g. copy) for ( ; _cur != _begin; ++_cur) { typename _ExtIterator::value_type tmp; in >> tmp; out << tmp; } // apply _functor to the range [_begin,_end) for ( ; _cur != _end; ++_cur) { typename _ExtIterator::value_type tmp; in >> tmp; _functor(tmp); out << tmp; } // leave part of the block after _end untouched if (_end.block_offset()) { _ExtIterator _last_block_end = _end - _end.block_offset() + _ExtIterator::block_type::size; for ( ; _cur != _last_block_end; ++_cur) { typename _ExtIterator::value_type tmp; in >> tmp; out << tmp; } } return _functor; } //! \brief External equivalent of std::generate //! \remark The implementation exploits \c \ buffered streams (computation and I/O overlapped) //! \param _begin object of model of \c ext_random_access_iterator concept //! \param _end object of model of \c ext_random_access_iterator concept //! \param _generator function object of model of \c std::Generator concept //! \param nbuffers number of buffers (blocks) for internal use (should be at least 2*D ) template void generate(_ExtIterator _begin, _ExtIterator _end, _Generator _generator, int_type nbuffers) { typedef typename _ExtIterator::block_type block_type; typedef buf_ostream buf_ostream_type; while (_begin.block_offset()) // go to the beginning of the block // of the external vector { if (_begin == _end) return; *_begin = _generator(); ++_begin; } _begin.flush(); // flush container // create buffered write stream for blocks buf_ostream_type outstream(_begin.bid(), nbuffers); assert(_begin.block_offset() == 0); // delay calling block_externally_updated() until the block is // completely filled (and written out) in outstream typename _ExtIterator::const_iterator prev_block = _begin; while (_end != _begin) { if (_begin.block_offset() == 0) { if (prev_block != _begin) { prev_block.block_externally_updated(); prev_block = _begin; } } *outstream = _generator(); ++_begin; ++outstream; } typename _ExtIterator::const_iterator out = _begin; while (out.block_offset()) // filling the rest of the block { *outstream = *out; ++out; ++outstream; } if (prev_block != out) prev_block.block_externally_updated(); _begin.flush(); } //! \brief External equivalent of std::find //! \remark The implementation exploits \c \ buffered streams (computation and I/O overlapped) //! \param _begin object of model of \c ext_random_access_iterator concept //! \param _end object of model of \c ext_random_access_iterator concept //! \param _value value that is equality comparable to the _ExtIterator's value type //! \param nbuffers number of buffers (blocks) for internal use (should be at least 2*D ) //! \return first iterator \c i in the range [_begin,_end) such that *( \c i ) == \c _value, if no //! such exists then \c _end template _ExtIterator find(_ExtIterator _begin, _ExtIterator _end, const _EqualityComparable & _value, int_type nbuffers) { if (_begin == _end) return _end; typedef buf_istream buf_istream_type; _begin.flush(); // flush container // create prefetching stream, buf_istream_type in(_begin.bid(), _end.bid() + ((_end.block_offset()) ? 1 : 0), nbuffers); _ExtIterator _cur = _begin - _begin.block_offset(); // skip part of the block before _begin untouched for ( ; _cur != _begin; ++_cur) ++in; // search in the the range [_begin,_end) for ( ; _cur != _end; ++_cur) { typename _ExtIterator::value_type tmp; in >> tmp; if (tmp == _value) return _cur; } return _cur; } //! \} __STXXL_END_NAMESPACE #endif // !STXXL_SCAN_HEADER // vim: et:ts=4:sw=4 stxxl-1.3.1/include/stxxl/bits/algo/sort_helper.h0000644000175000017500000001172311513611117021702 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/algo/sort_helper.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2002-2003 Roman Dementiev * Copyright (C) 2009, 2010 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_SORT_HELPER_HEADER #define STXXL_SORT_HELPER_HEADER #include #include #include #include __STXXL_BEGIN_NAMESPACE //! \internal namespace sort_helper { template inline void verify_sentinel_strict_weak_ordering(StrictWeakOrdering cmp) { assert(!cmp(cmp.min_value(), cmp.min_value())); assert(cmp(cmp.min_value(), cmp.max_value())); assert(!cmp(cmp.max_value(), cmp.min_value())); assert(!cmp(cmp.max_value(), cmp.max_value())); STXXL_UNUSED(cmp); } template struct trigger_entry { typedef BlockTp_ block_type; typedef typename block_type::bid_type bid_type; typedef ValTp_ value_type; bid_type bid; value_type value; operator bid_type () { return bid; } }; template struct trigger_entry_cmp : public std::binary_function { typedef TriggerEntryTp_ trigger_entry_type; ValueCmp_ cmp; trigger_entry_cmp(ValueCmp_ c) : cmp(c) { } trigger_entry_cmp(const trigger_entry_cmp & a) : cmp(a.cmp) { } bool operator () (const trigger_entry_type & a, const trigger_entry_type & b) const { return cmp(a.value, b.value); } }; template struct run_cursor2_cmp : public std::binary_function, run_cursor2, bool> { typedef run_cursor2 cursor_type; value_cmp cmp; run_cursor2_cmp(value_cmp c) : cmp(c) { } run_cursor2_cmp(const run_cursor2_cmp & a) : cmp(a.cmp) { } inline bool operator () (const cursor_type & a, const cursor_type & b) const { if (UNLIKELY(b.empty())) return true; // sentinel emulation if (UNLIKELY(a.empty())) return false; // sentinel emulation return (cmp(a.current(), b.current())); } }; // this function is used by parallel mergers template inline unsigned_type count_elements_less_equal(const SequenceVector & seqs, const ValueType & bound, Comparator cmp) { typedef typename SequenceVector::size_type seqs_size_type; typedef typename SequenceVector::value_type::first_type iterator; unsigned_type count = 0; for (seqs_size_type i = 0; i < seqs.size(); ++i) { iterator position = std::upper_bound(seqs[i].first, seqs[i].second, bound, cmp); STXXL_VERBOSE1("less equal than " << position - seqs[i].first); count += position - seqs[i].first; } STXXL_VERBOSE1("finished loop"); return count; } // this function is used by parallel mergers template inline void refill_or_remove_empty_sequences(SequenceVector & seqs, BufferPtrVector & buffers, Prefetcher & prefetcher) { typedef typename SequenceVector::size_type seqs_size_type; for (seqs_size_type i = 0; i < seqs.size(); ++i) { if (seqs[i].first == seqs[i].second) // run empty { if (prefetcher.block_consumed(buffers[i])) { seqs[i].first = buffers[i]->begin(); // reset iterator seqs[i].second = buffers[i]->end(); STXXL_VERBOSE1("block ran empty " << i); } else { seqs.erase(seqs.begin() + i); // remove this sequence buffers.erase(buffers.begin() + i); STXXL_VERBOSE1("seq removed " << i); --i; // don't skip the next sequence } } } } } __STXXL_END_NAMESPACE #endif // !STXXL_SORT_HELPER_HEADER // vim: et:ts=4:sw=4 stxxl-1.3.1/include/stxxl/bits/algo/sort.h0000644000175000017500000011137611536214454020360 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/algo/sort.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2002-2003 Roman Dementiev * Copyright (C) 2006 Johannes Singler * Copyright (C) 2008-2011 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_SORT_HEADER #define STXXL_SORT_HEADER #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include __STXXL_BEGIN_NAMESPACE //! \addtogroup stlalgo //! \{ /*! \internal */ namespace sort_local { template struct read_next_after_write_completed { block_type * block; bid_type bid; request_ptr * req; void operator () (request * /*completed_req*/) { *req = block->read(bid); } }; template < typename block_type, typename run_type, typename input_bid_iterator, typename value_cmp> void create_runs( input_bid_iterator it, run_type ** runs, int_type nruns, int_type _m, value_cmp cmp) { typedef typename block_type::value_type type; typedef typename block_type::bid_type bid_type; STXXL_VERBOSE1("stxxl::create_runs nruns=" << nruns << " m=" << _m); int_type m2 = _m / 2; block_manager * bm = block_manager::get_instance(); block_type * Blocks1 = new block_type[m2]; block_type * Blocks2 = new block_type[m2]; bid_type * bids1 = new bid_type[m2]; bid_type * bids2 = new bid_type[m2]; request_ptr * read_reqs1 = new request_ptr[m2]; request_ptr * read_reqs2 = new request_ptr[m2]; request_ptr * write_reqs = new request_ptr[m2]; read_next_after_write_completed * next_run_reads = new read_next_after_write_completed[m2]; disk_queues::get_instance()->set_priority_op(request_queue::WRITE); int_type i; int_type run_size = 0; assert(nruns >= 2); run_size = runs[0]->size(); assert(run_size == m2); for (i = 0; i < run_size; ++i) { STXXL_VERBOSE1("stxxl::create_runs posting read " << long(Blocks1[i].elem)); bids1[i] = *(it++); read_reqs1[i] = Blocks1[i].read(bids1[i]); } run_size = runs[1]->size(); for (i = 0; i < run_size; ++i) { STXXL_VERBOSE1("stxxl::create_runs posting read " << long(Blocks2[i].elem)); bids2[i] = *(it++); read_reqs2[i] = Blocks2[i].read(bids2[i]); } for (int_type k = 0; k < nruns - 1; ++k) { run_type * run = runs[k]; run_size = run->size(); assert(run_size == m2); #ifndef NDEBUG int_type next_run_size = runs[k + 1]->size(); #endif assert((next_run_size == m2) || (next_run_size <= m2 && k == nruns - 2)); STXXL_VERBOSE1("stxxl::create_runs start waiting read_reqs1"); wait_all(read_reqs1, run_size); STXXL_VERBOSE1("stxxl::create_runs finish waiting read_reqs1"); for (i = 0; i < run_size; ++i) bm->delete_block(bids1[i]); potentially_parallel:: sort(make_element_iterator(Blocks1, 0), make_element_iterator(Blocks1, run_size * block_type::size), cmp); STXXL_VERBOSE1("stxxl::create_runs start waiting write_reqs"); if (k > 0) wait_all(write_reqs, m2); STXXL_VERBOSE1("stxxl::create_runs finish waiting write_reqs"); int_type runplus2size = (k < nruns - 2) ? runs[k + 2]->size() : 0; for (i = 0; i < m2; ++i) { STXXL_VERBOSE1("stxxl::create_runs posting write " << long(Blocks1[i].elem)); (*run)[i].value = Blocks1[i][0]; if (i >= runplus2size) { write_reqs[i] = Blocks1[i].write((*run)[i].bid); } else { next_run_reads[i].block = Blocks1 + i; next_run_reads[i].req = read_reqs1 + i; bids1[i] = next_run_reads[i].bid = *(it++); write_reqs[i] = Blocks1[i].write((*run)[i].bid, next_run_reads[i]); } } std::swap(Blocks1, Blocks2); std::swap(bids1, bids2); std::swap(read_reqs1, read_reqs2); } run_type * run = runs[nruns - 1]; run_size = run->size(); STXXL_VERBOSE1("stxxl::create_runs start waiting read_reqs1"); wait_all(read_reqs1, run_size); STXXL_VERBOSE1("stxxl::create_runs finish waiting read_reqs1"); for (i = 0; i < run_size; ++i) bm->delete_block(bids1[i]); potentially_parallel:: sort(make_element_iterator(Blocks1, 0), make_element_iterator(Blocks1, run_size * block_type::size), cmp); STXXL_VERBOSE1("stxxl::create_runs start waiting write_reqs"); wait_all(write_reqs, m2); STXXL_VERBOSE1("stxxl::create_runs finish waiting write_reqs"); for (i = 0; i < run_size; ++i) { STXXL_VERBOSE1("stxxl::create_runs posting write " << long(Blocks1[i].elem)); (*run)[i].value = Blocks1[i][0]; write_reqs[i] = Blocks1[i].write((*run)[i].bid); } STXXL_VERBOSE1("stxxl::create_runs start waiting write_reqs"); wait_all(write_reqs, run_size); STXXL_VERBOSE1("stxxl::create_runs finish waiting write_reqs"); delete[] Blocks1; delete[] Blocks2; delete[] bids1; delete[] bids2; delete[] read_reqs1; delete[] read_reqs2; delete[] write_reqs; delete[] next_run_reads; } template bool check_sorted_runs(run_type ** runs, unsigned_type nruns, unsigned_type m, value_cmp cmp) { typedef typename block_type::value_type value_type; STXXL_MSG("check_sorted_runs Runs: " << nruns); unsigned_type irun = 0; for (irun = 0; irun < nruns; ++irun) { const unsigned_type nblocks_per_run = runs[irun]->size(); unsigned_type blocks_left = nblocks_per_run; block_type * blocks = new block_type[m]; request_ptr * reqs = new request_ptr[m]; value_type last = cmp.min_value(); for (unsigned_type off = 0; off < nblocks_per_run; off += m) { const unsigned_type nblocks = STXXL_MIN(blocks_left, m); const unsigned_type nelements = nblocks * block_type::size; blocks_left -= nblocks; for (unsigned_type j = 0; j < nblocks; ++j) { reqs[j] = blocks[j].read((*runs[irun])[j + off].bid); } wait_all(reqs, reqs + nblocks); if (off && cmp(blocks[0][0], last)) { STXXL_MSG("check_sorted_runs wrong first value in the run " << irun); STXXL_MSG(" first value: " << blocks[0][0]); STXXL_MSG(" last value: " << last); for (unsigned_type k = 0; k < block_type::size; ++k) STXXL_MSG("Element " << k << " in the block is :" << blocks[0][k]); return false; } for (unsigned_type j = 0; j < nblocks; ++j) { if (!(blocks[j][0] == (*runs[irun])[j + off].value)) { STXXL_MSG("check_sorted_runs wrong trigger in the run " << irun << " block " << (j + off)); STXXL_MSG(" trigger value: " << (*runs[irun])[j + off].value); STXXL_MSG("Data in the block:"); for (unsigned_type k = 0; k < block_type::size; ++k) STXXL_MSG("Element " << k << " in the block is :" << blocks[j][k]); STXXL_MSG("BIDS:"); for (unsigned_type k = 0; k < nblocks; ++k) { if (k == j) STXXL_MSG("Bad one comes next."); STXXL_MSG("BID " << (k + off) << " is: " << ((*runs[irun])[k + off].bid)); } return false; } } if (!stxxl::is_sorted(make_element_iterator(blocks, 0), make_element_iterator(blocks, nelements), cmp)) { STXXL_MSG("check_sorted_runs wrong order in the run " << irun); STXXL_MSG("Data in blocks:"); for (unsigned_type j = 0; j < nblocks; ++j) { for (unsigned_type k = 0; k < block_type::size; ++k) STXXL_MSG(" Element " << k << " in block " << (j + off) << " is :" << blocks[j][k]); } STXXL_MSG("BIDS:"); for (unsigned_type k = 0; k < nblocks; ++k) { STXXL_MSG("BID " << (k + off) << " is: " << ((*runs[irun])[k + off].bid)); } return false; } last = blocks[nblocks - 1][block_type::size - 1]; } assert(blocks_left == 0); delete[] reqs; delete[] blocks; } return true; } template void merge_runs(run_type ** in_runs, int_type nruns, run_type * out_run, unsigned_type _m, value_cmp cmp) { typedef typename block_type::value_type value_type; typedef typename run_type::value_type trigger_entry_type; typedef block_prefetcher prefetcher_type; typedef run_cursor2 run_cursor_type; typedef sort_helper::run_cursor2_cmp run_cursor2_cmp_type; run_type consume_seq(out_run->size()); int_type * prefetch_seq = new int_type[out_run->size()]; typename run_type::iterator copy_start = consume_seq.begin(); for (int_type i = 0; i < nruns; i++) { // TODO: try to avoid copy copy_start = std::copy( in_runs[i]->begin(), in_runs[i]->end(), copy_start); } std::stable_sort(consume_seq.begin(), consume_seq.end(), sort_helper::trigger_entry_cmp(cmp) _STXXL_SORT_TRIGGER_FORCE_SEQUENTIAL); int_type disks_number = config::get_instance()->disks_number(); #ifdef PLAY_WITH_OPT_PREF const int_type n_write_buffers = 4 * disks_number; #else const int_type n_prefetch_buffers = STXXL_MAX(2 * disks_number, (3 * (int_type(_m) - nruns) / 4)); const int_type n_write_buffers = STXXL_MAX(2 * disks_number, int_type(_m) - nruns - n_prefetch_buffers); #if STXXL_SORT_OPTIMAL_PREFETCHING // heuristic const int_type n_opt_prefetch_buffers = 2 * disks_number + (3 * (n_prefetch_buffers - 2 * disks_number)) / 10; #endif #endif #if STXXL_SORT_OPTIMAL_PREFETCHING compute_prefetch_schedule( consume_seq, prefetch_seq, n_opt_prefetch_buffers, disks_number); #else for (unsigned_type i = 0; i < out_run->size(); i++) prefetch_seq[i] = i; #endif prefetcher_type prefetcher(consume_seq.begin(), consume_seq.end(), prefetch_seq, nruns + n_prefetch_buffers); buffered_writer writer(n_write_buffers, n_write_buffers / 2); int_type out_run_size = out_run->size(); block_type * out_buffer = writer.get_free_block(); //If parallelism is activated, one can still fall back to the //native merge routine by setting stxxl::SETTINGS::native_merge= true, //otherwise, it is used anyway. if (do_parallel_merge()) { #if STXXL_PARALLEL_MULTIWAY_MERGE // begin of STL-style merging typedef stxxl::int64 diff_type; typedef std::pair sequence; typedef typename std::vector::size_type seqs_size_type; std::vector seqs(nruns); std::vector buffers(nruns); for (int_type i = 0; i < nruns; i++) // initialize sequences { buffers[i] = prefetcher.pull_block(); // get first block of each run seqs[i] = std::make_pair(buffers[i]->begin(), buffers[i]->end()); // this memory location stays the same, only the data is exchanged } #if STXXL_CHECK_ORDER_IN_SORTS value_type last_elem = cmp.min_value(); #endif diff_type num_currently_mergeable = 0; for (int_type j = 0; j < out_run_size; ++j) // for the whole output run, out_run_size is in blocks { diff_type rest = block_type::size; // elements still to merge for this output block STXXL_VERBOSE1("output block " << j); do { if (num_currently_mergeable < rest) { if (prefetcher.empty()) { // anything remaining is already in memory num_currently_mergeable = (out_run_size - j) * block_type::size - (block_type::size - rest); } else { num_currently_mergeable = sort_helper::count_elements_less_equal( seqs, consume_seq[prefetcher.pos()].value, cmp); } } diff_type output_size = STXXL_MIN(num_currently_mergeable, rest); // at most rest elements STXXL_VERBOSE1("before merge " << output_size); stxxl::parallel::multiway_merge(seqs.begin(), seqs.end(), out_buffer->end() - rest, cmp, output_size); // sequence iterators are progressed appropriately rest -= output_size; num_currently_mergeable -= output_size; STXXL_VERBOSE1("after merge"); sort_helper::refill_or_remove_empty_sequences(seqs, buffers, prefetcher); } while (rest > 0 && seqs.size() > 0); #if STXXL_CHECK_ORDER_IN_SORTS if (!stxxl::is_sorted(out_buffer->begin(), out_buffer->end(), cmp)) { for (value_type * i = out_buffer->begin() + 1; i != out_buffer->end(); i++) if (cmp(*i, *(i - 1))) { STXXL_VERBOSE1("Error at position " << (i - out_buffer->begin())); } assert(false); } if (j > 0) // do not check in first iteration assert(cmp((*out_buffer)[0], last_elem) == false); last_elem = (*out_buffer)[block_type::size - 1]; #endif (*out_run)[j].value = (*out_buffer)[0]; // save smallest value out_buffer = writer.write(out_buffer, (*out_run)[j].bid); } // end of STL-style merging #else STXXL_THROW_UNREACHABLE(); #endif } else { // begin of native merging procedure loser_tree losers(&prefetcher, nruns, run_cursor2_cmp_type(cmp)); #if STXXL_CHECK_ORDER_IN_SORTS value_type last_elem = cmp.min_value(); #endif for (int_type i = 0; i < out_run_size; ++i) { losers.multi_merge(out_buffer->elem, out_buffer->elem + block_type::size); (*out_run)[i].value = *(out_buffer->elem); #if STXXL_CHECK_ORDER_IN_SORTS assert(stxxl::is_sorted( out_buffer->begin(), out_buffer->end(), cmp)); if (i) assert(cmp(*(out_buffer->elem), last_elem) == false); last_elem = (*out_buffer).elem[block_type::size - 1]; #endif out_buffer = writer.write(out_buffer, (*out_run)[i].bid); } // end of native merging procedure } delete[] prefetch_seq; block_manager * bm = block_manager::get_instance(); for (int_type i = 0; i < nruns; ++i) { unsigned_type sz = in_runs[i]->size(); for (unsigned_type j = 0; j < sz; ++j) bm->delete_block((*in_runs[i])[j].bid); delete in_runs[i]; } } template simple_vector > * sort_blocks(input_bid_iterator input_bids, unsigned_type _n, unsigned_type _m, value_cmp cmp ) { typedef typename block_type::value_type type; typedef typename block_type::bid_type bid_type; typedef sort_helper::trigger_entry trigger_entry_type; typedef simple_vector run_type; typedef typename interleaved_alloc_traits::strategy interleaved_alloc_strategy; unsigned_type m2 = _m / 2; unsigned_type full_runs = _n / m2; unsigned_type partial_runs = ((_n % m2) ? 1 : 0); unsigned_type nruns = full_runs + partial_runs; unsigned_type i; block_manager * mng = block_manager::get_instance(); //STXXL_VERBOSE ("n=" << _n << " nruns=" << nruns << "=" << full_runs << "+" << partial_runs); double begin = timestamp(), after_runs_creation, end; run_type ** runs = new run_type *[nruns]; for (i = 0; i < full_runs; i++) runs[i] = new run_type(m2); if (partial_runs) runs[i] = new run_type(_n - full_runs * m2); for (i = 0; i < nruns; ++i) mng->new_blocks(alloc_strategy(), make_bid_iterator(runs[i]->begin()), make_bid_iterator(runs[i]->end())); sort_local::create_runs(input_bids, runs, nruns, _m, cmp); after_runs_creation = timestamp(); double io_wait_after_rf = stats::get_instance()->get_io_wait_time(); disk_queues::get_instance()->set_priority_op(request_queue::WRITE); const int_type merge_factor = optimal_merge_factor(nruns, _m); run_type ** new_runs; while (nruns > 1) { int_type new_nruns = div_ceil(nruns, merge_factor); STXXL_VERBOSE("Starting new merge phase: nruns: " << nruns << " opt_merge_factor: " << merge_factor << " m:" << _m << " new_nruns: " << new_nruns); new_runs = new run_type *[new_nruns]; int_type runs_left = nruns; int_type cur_out_run = 0; int_type blocks_in_new_run = 0; while (runs_left > 0) { int_type runs2merge = STXXL_MIN(runs_left, merge_factor); blocks_in_new_run = 0; for (unsigned_type i = nruns - runs_left; i < (nruns - runs_left + runs2merge); i++) blocks_in_new_run += runs[i]->size(); // allocate run new_runs[cur_out_run++] = new run_type(blocks_in_new_run); runs_left -= runs2merge; } // allocate blocks for the new runs if (cur_out_run == 1 && blocks_in_new_run == int_type(_n) && !input_bids->is_managed()) { // if we sort a file we can reuse the input bids for the output input_bid_iterator cur = input_bids; for (int_type i = 0; cur != (input_bids + _n); ++cur) { (*new_runs[0])[i++].bid = *cur; } bid_type & firstBID = (*new_runs[0])[0].bid; if (firstBID.is_managed()) { // the first block does not belong to the file // need to reallocate it mng->new_block(FR(), firstBID); } bid_type & lastBID = (*new_runs[0])[_n - 1].bid; if (lastBID.is_managed()) { // the first block does not belong to the file // need to reallocate it mng->new_block(FR(), lastBID); } } else { mng->new_blocks(interleaved_alloc_strategy(new_nruns, alloc_strategy()), RunsToBIDArrayAdaptor2(new_runs, 0, new_nruns, blocks_in_new_run), RunsToBIDArrayAdaptor2(new_runs, _n, new_nruns, blocks_in_new_run)); } // merge all runs_left = nruns; cur_out_run = 0; while (runs_left > 0) { int_type runs2merge = STXXL_MIN(runs_left, merge_factor); #if STXXL_CHECK_ORDER_IN_SORTS assert((check_sorted_runs(runs + nruns - runs_left, runs2merge, m2, cmp))); #endif STXXL_VERBOSE("Merging " << runs2merge << " runs"); merge_runs(runs + nruns - runs_left, runs2merge, *(new_runs + (cur_out_run++)), _m, cmp ); runs_left -= runs2merge; } nruns = new_nruns; delete[] runs; runs = new_runs; } run_type * result = *runs; delete[] runs; end = timestamp(); STXXL_VERBOSE("Elapsed time : " << end - begin << " s. Run creation time: " << after_runs_creation - begin << " s"); STXXL_VERBOSE("Time in I/O wait(rf): " << io_wait_after_rf << " s"); STXXL_VERBOSE(*stats::get_instance()); STXXL_UNUSED(begin + after_runs_creation + end + io_wait_after_rf); return result; } } /*! \page comparison Comparison concept Model of \b Comparison concept must: - provide \b operator(a,b) that returns comparison result of two user types, must define strict weak ordering - provide \b max_value method that returns a value that is \b strictly \b greater than all other objects of user type, - provide \b min_value method that returns a value that is \b strictly \b less than all other objects of user type, - \b Note: when using unsigned integral types as key in user types, the value 0 cannot be used as a key value of the data to be sorted because it would conflict with the sentinel value returned by \b min_value Example: comparator class \b my_less_int \verbatim struct my_less_int { bool operator() (int a, int b) const { return a < b; } int min_value() const { return std::numeric_limits::min(); }; int max_value() const { return std::numeric_limits::max(); }; }; \endverbatim Example: comparator class \b my_less, could be instantiated as e.g. \b my_less , \b my_less , ... \verbatim template struct my_less { typedef Tp value_type; bool operator() (const value_type & a, const value_type & b) const { return a < b; } value_type min_value() const { return std::numeric_limits::min(); }; value_type max_value() const { return std::numeric_limits::max(); }; }; \endverbatim */ //! \brief Sort records comparison-based //! \param first object of model of \c ext_random_access_iterator concept //! \param last object of model of \c ext_random_access_iterator concept //! \param cmp comparison object //! \param M amount of memory for internal use (in bytes) //! \remark Implements external merge sort described in [Dementiev & Sanders'03] //! \remark non-stable template void sort(ExtIterator_ first, ExtIterator_ last, StrictWeakOrdering_ cmp, unsigned_type M) { sort_helper::verify_sentinel_strict_weak_ordering(cmp); typedef simple_vector > run_type; typedef typename ExtIterator_::vector_type::value_type value_type; typedef typename ExtIterator_::block_type block_type; unsigned_type n = 0; block_manager * mng = block_manager::get_instance(); first.flush(); if ((last - first) * sizeof(value_type) * sort_memory_usage_factor() < M) { stl_in_memory_sort(first, last, cmp); } else { if (!(2 * block_type::raw_size * sort_memory_usage_factor() <= M)) { throw bad_parameter("stxxl::sort(): INSUFFICIENT MEMORY provided, please increase parameter 'M'"); } if (first.block_offset()) { if (last.block_offset()) // first and last element are // not the first elements of their block { typename ExtIterator_::block_type * first_block = new typename ExtIterator_::block_type; typename ExtIterator_::block_type * last_block = new typename ExtIterator_::block_type; typename ExtIterator_::bid_type first_bid, last_bid; request_ptr req; req = first_block->read(*first.bid()); mng->new_block(FR(), first_bid); // try to overlap mng->new_block(FR(), last_bid); req->wait(); req = last_block->read(*last.bid()); unsigned_type i = 0; for ( ; i < first.block_offset(); ++i) { first_block->elem[i] = cmp.min_value(); } req->wait(); req = first_block->write(first_bid); for (i = last.block_offset(); i < block_type::size; ++i) { last_block->elem[i] = cmp.max_value(); } req->wait(); req = last_block->write(last_bid); n = last.bid() - first.bid() + 1; std::swap(first_bid, *first.bid()); std::swap(last_bid, *last.bid()); req->wait(); delete first_block; delete last_block; run_type * out = sort_local::sort_blocks< typename ExtIterator_::block_type, typename ExtIterator_::vector_type::alloc_strategy_type, typename ExtIterator_::bids_container_iterator> (first.bid(), n, M / sort_memory_usage_factor() / block_type::raw_size, cmp); first_block = new typename ExtIterator_::block_type; last_block = new typename ExtIterator_::block_type; typename ExtIterator_::block_type * sorted_first_block = new typename ExtIterator_::block_type; typename ExtIterator_::block_type * sorted_last_block = new typename ExtIterator_::block_type; request_ptr * reqs = new request_ptr[2]; reqs[0] = first_block->read(first_bid); reqs[1] = sorted_first_block->read((*(out->begin())).bid); reqs[0]->wait(); reqs[1]->wait(); reqs[0] = last_block->read(last_bid); reqs[1] = sorted_last_block->read(((*out)[out->size() - 1]).bid); for (i = first.block_offset(); i < block_type::size; i++) { first_block->elem[i] = sorted_first_block->elem[i]; } reqs[0]->wait(); reqs[1]->wait(); req = first_block->write(first_bid); for (i = 0; i < last.block_offset(); ++i) { last_block->elem[i] = sorted_last_block->elem[i]; } req->wait(); req = last_block->write(last_bid); mng->delete_block(out->begin()->bid); mng->delete_block((*out)[out->size() - 1].bid); *first.bid() = first_bid; *last.bid() = last_bid; typename run_type::iterator it = out->begin(); ++it; typename ExtIterator_::bids_container_iterator cur_bid = first.bid(); ++cur_bid; for ( ; cur_bid != last.bid(); ++cur_bid, ++it) { *cur_bid = (*it).bid; } delete first_block; delete sorted_first_block; delete sorted_last_block; delete[] reqs; delete out; req->wait(); delete last_block; } else { // first element is // not the first element of its block typename ExtIterator_::block_type * first_block = new typename ExtIterator_::block_type; typename ExtIterator_::bid_type first_bid; request_ptr req; req = first_block->read(*first.bid()); mng->new_block(FR(), first_bid); // try to overlap req->wait(); unsigned_type i = 0; for ( ; i < first.block_offset(); ++i) { first_block->elem[i] = cmp.min_value(); } req = first_block->write(first_bid); n = last.bid() - first.bid(); std::swap(first_bid, *first.bid()); req->wait(); delete first_block; run_type * out = sort_local::sort_blocks< typename ExtIterator_::block_type, typename ExtIterator_::vector_type::alloc_strategy_type, typename ExtIterator_::bids_container_iterator> (first.bid(), n, M / sort_memory_usage_factor() / block_type::raw_size, cmp); first_block = new typename ExtIterator_::block_type; typename ExtIterator_::block_type * sorted_first_block = new typename ExtIterator_::block_type; request_ptr * reqs = new request_ptr[2]; reqs[0] = first_block->read(first_bid); reqs[1] = sorted_first_block->read((*(out->begin())).bid); reqs[0]->wait(); reqs[1]->wait(); for (i = first.block_offset(); i < block_type::size; ++i) { first_block->elem[i] = sorted_first_block->elem[i]; } req = first_block->write(first_bid); mng->delete_block(out->begin()->bid); *first.bid() = first_bid; typename run_type::iterator it = out->begin(); ++it; typename ExtIterator_::bids_container_iterator cur_bid = first.bid(); ++cur_bid; for ( ; cur_bid != last.bid(); ++cur_bid, ++it) { *cur_bid = (*it).bid; } *cur_bid = (*it).bid; delete sorted_first_block; delete[] reqs; delete out; req->wait(); delete first_block; } } else { if (last.block_offset()) // last is // not the first element of its block { typename ExtIterator_::block_type * last_block = new typename ExtIterator_::block_type; typename ExtIterator_::bid_type last_bid; request_ptr req; unsigned_type i; req = last_block->read(*last.bid()); mng->new_block(FR(), last_bid); req->wait(); for (i = last.block_offset(); i < block_type::size; ++i) { last_block->elem[i] = cmp.max_value(); } req = last_block->write(last_bid); n = last.bid() - first.bid() + 1; std::swap(last_bid, *last.bid()); req->wait(); delete last_block; run_type * out = sort_local::sort_blocks< typename ExtIterator_::block_type, typename ExtIterator_::vector_type::alloc_strategy_type, typename ExtIterator_::bids_container_iterator> (first.bid(), n, M / sort_memory_usage_factor() / block_type::raw_size, cmp); last_block = new typename ExtIterator_::block_type; typename ExtIterator_::block_type * sorted_last_block = new typename ExtIterator_::block_type; request_ptr * reqs = new request_ptr[2]; reqs[0] = last_block->read(last_bid); reqs[1] = sorted_last_block->read(((*out)[out->size() - 1]).bid); reqs[0]->wait(); reqs[1]->wait(); for (i = 0; i < last.block_offset(); ++i) { last_block->elem[i] = sorted_last_block->elem[i]; } req = last_block->write(last_bid); mng->delete_block((*out)[out->size() - 1].bid); *last.bid() = last_bid; typename run_type::iterator it = out->begin(); typename ExtIterator_::bids_container_iterator cur_bid = first.bid(); for ( ; cur_bid != last.bid(); ++cur_bid, ++it) { *cur_bid = (*it).bid; } delete sorted_last_block; delete[] reqs; delete out; req->wait(); delete last_block; } else { // first and last element are first elements of their of blocks n = last.bid() - first.bid(); run_type * out = sort_local::sort_blocks (first.bid(), n, M / sort_memory_usage_factor() / block_type::raw_size, cmp); typename run_type::iterator it = out->begin(); typename ExtIterator_::bids_container_iterator cur_bid = first.bid(); for ( ; cur_bid != last.bid(); ++cur_bid, ++it) { *cur_bid = (*it).bid; } delete out; } } } #if STXXL_CHECK_ORDER_IN_SORTS typedef typename ExtIterator_::const_iterator const_iterator; assert(stxxl::is_sorted(const_iterator(first), const_iterator(last), cmp)); #endif } //! \} __STXXL_END_NAMESPACE #endif // !STXXL_SORT_HEADER // vim: et:ts=4:sw=4 stxxl-1.3.1/include/stxxl/bits/namespace.h0000644000175000017500000000122011024753374020366 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/namespace.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2007 Roman Dementiev * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_NAMESPACE_HEADER #define STXXL_NAMESPACE_HEADER #define __STXXL_BEGIN_NAMESPACE namespace stxxl { #define __STXXL_END_NAMESPACE } #endif // !STXXL_NAMESPACE_HEADER stxxl-1.3.1/include/stxxl/bits/parallel.h0000644000175000017500000001525711535404612020240 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/parallel.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2008-2010 Andreas Beckmann * Copyright (C) 2011 Johannes Singler * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_PARALLEL_HEADER #define STXXL_PARALLEL_HEADER #undef STXXL_PARALLEL #undef STXXL_PARALLEL_MODE #if defined(_GLIBCXX_PARALLEL) || defined (STXXL_PARALLEL_MODE_EXPLICIT) #define STXXL_PARALLEL_MODE #endif #if defined(PARALLEL_MODE) && defined (__MCSTL__) #error (_GLIBCXX_PARALLEL or STXXL_PARALLEL_MODE_EXPLICIT) and __MCSTL__ are defined #endif #if defined(STXXL_PARALLEL_MODE) || defined (__MCSTL__) #define STXXL_PARALLEL 1 #else #define STXXL_PARALLEL 0 #endif #include #ifdef STXXL_PARALLEL_MODE #include #endif #ifdef __MCSTL__ #include #include #include #endif #if STXXL_PARALLEL #include #endif #include #include #if defined(_GLIBCXX_PARALLEL) //use _STXXL_FORCE_SEQUENTIAL to tag calls which are not worthwhile parallelizing #define _STXXL_FORCE_SEQUENTIAL , __gnu_parallel::sequential_tag() #elif defined(__MCSTL__) #define _STXXL_FORCE_SEQUENTIAL , mcstl::sequential_tag() #else #define _STXXL_FORCE_SEQUENTIAL #endif #if 0 // sorting triggers is done sequentially #define _STXXL_SORT_TRIGGER_FORCE_SEQUENTIAL _STXXL_FORCE_SEQUENTIAL #else // sorting triggers may be parallelized #define _STXXL_SORT_TRIGGER_FORCE_SEQUENTIAL #endif #if !STXXL_PARALLEL #undef STXXL_PARALLEL_MULTIWAY_MERGE #define STXXL_PARALLEL_MULTIWAY_MERGE 0 #endif #if defined(STXXL_PARALLEL_MODE) && ((__GNUC__ * 10000 + __GNUC_MINOR__ * 100) < 40400) #undef STXXL_PARALLEL_MULTIWAY_MERGE #define STXXL_PARALLEL_MULTIWAY_MERGE 0 #endif #if !defined(STXXL_PARALLEL_MULTIWAY_MERGE) #define STXXL_PARALLEL_MULTIWAY_MERGE 1 #endif #if !defined(STXXL_NOT_CONSIDER_SORT_MEMORY_OVERHEAD) #define STXXL_NOT_CONSIDER_SORT_MEMORY_OVERHEAD 0 #endif #ifdef STXXL_PARALLEL_MODE_EXPLICIT #include #else #include #endif __STXXL_BEGIN_NAMESPACE inline unsigned sort_memory_usage_factor() { #if STXXL_PARALLEL && !STXXL_NOT_CONSIDER_SORT_MEMORY_OVERHEAD && defined(STXXL_PARALLEL_MODE) return (__gnu_parallel::_Settings::get().sort_algorithm == __gnu_parallel::MWMS && omp_get_max_threads() > 1) ? 2 : 1; //memory overhead for multiway mergesort #elif STXXL_PARALLEL && !STXXL_NOT_CONSIDER_SORT_MEMORY_OVERHEAD && defined(__MCSTL__) return (mcstl::SETTINGS::sort_algorithm == mcstl::SETTINGS::MWMS && mcstl::SETTINGS::num_threads > 1) ? 2 : 1; //memory overhead for multiway mergesort #else return 1; //no overhead #endif } inline bool do_parallel_merge() { #if STXXL_PARALLEL_MULTIWAY_MERGE && defined(STXXL_PARALLEL_MODE) return !stxxl::SETTINGS::native_merge && omp_get_max_threads() >= 1; #elif STXXL_PARALLEL_MULTIWAY_MERGE && defined(__MCSTL__) return !stxxl::SETTINGS::native_merge && mcstl::SETTINGS::num_threads >= 1; #else return false; #endif } namespace potentially_parallel { #ifdef STXXL_PARALLEL_MODE_EXPLICIT using __gnu_parallel::sort; using __gnu_parallel::random_shuffle; #else using std::sort; using std::random_shuffle; #endif } namespace parallel { #if STXXL_PARALLEL /** @brief Multi-way merging dispatcher. * @param seqs_begin Begin iterator of iterator pair input sequence. * @param seqs_end End iterator of iterator pair input sequence. * @param target Begin iterator out output sequence. * @param comp Comparator. * @param length Maximum length to merge. * @return End iterator of output sequence. */ template RandomAccessIterator3 multiway_merge(RandomAccessIteratorPairIterator seqs_begin, RandomAccessIteratorPairIterator seqs_end, RandomAccessIterator3 target, Comparator comp, DiffType length) { #if defined(STXXL_PARALLEL_MODE) && ((__GNUC__ * 10000 + __GNUC_MINOR__ * 100) >= 40400) return __gnu_parallel::multiway_merge(seqs_begin, seqs_end, target, length, comp); #elif defined(STXXL_PARALLEL_MODE) return __gnu_parallel::multiway_merge(seqs_begin, seqs_end, target, comp, length); #elif defined(__MCSTL__) typedef typename compat::make_signed::type difference_type; return mcstl::multiway_merge(seqs_begin, seqs_end, target, comp, difference_type(length), false); #else #error "no implementation found for multiway_merge()" #endif } /** @brief Multi-way merging front-end. * @param seqs_begin Begin iterator of iterator pair input sequence. * @param seqs_end End iterator of iterator pair input sequence. * @param target Begin iterator out output sequence. * @param comp Comparator. * @param length Maximum length to merge. * @return End iterator of output sequence. * @pre For each @c i, @c seqs_begin[i].second must be the end marker of the sequence, but also reference the one more sentinel element. */ template RandomAccessIterator3 multiway_merge_sentinel(RandomAccessIteratorPairIterator seqs_begin, RandomAccessIteratorPairIterator seqs_end, RandomAccessIterator3 target, Comparator comp, DiffType length) { #if defined(STXXL_PARALLEL_MODE) && ((__GNUC__ * 10000 + __GNUC_MINOR__ * 100) >= 40400) return __gnu_parallel::multiway_merge_sentinels(seqs_begin, seqs_end, target, length, comp); #elif defined(STXXL_PARALLEL_MODE) return __gnu_parallel::multiway_merge_sentinels(seqs_begin, seqs_end, target, comp, length); #elif defined(__MCSTL__) typedef typename compat::make_signed::type difference_type; return mcstl::multiway_merge_sentinel(seqs_begin, seqs_end, target, comp, difference_type(length), false); #else #error "no implementation found for multiway_merge_sentinel()" #endif } #endif } __STXXL_END_NAMESPACE #endif // !STXXL_PARALLEL_HEADER // vim: et:ts=4:sw=4 stxxl-1.3.1/include/stxxl/bits/compat/0000755000175000017500000000000011536252421017544 5ustar andreasandreasstxxl-1.3.1/include/stxxl/bits/compat/shared_ptr.h0000644000175000017500000000371711535455344022070 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/compat/shared_ptr.h * * compatibility interface to shared_ptr (C++0x, TR1 or boost) * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2011 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_HEADER__COMPAT__SHARED_PTR_H_ #define STXXL_HEADER__COMPAT__SHARED_PTR_H_ #include #if defined(__GNUG__) && !defined(__GXX_EXPERIMENTAL_CXX0X__) \ && ((__GNUC__ * 10000 + __GNUC_MINOR__ * 100) >= 40200) \ && (!defined(__ICC) || (__ICC >= 1100)) #include #endif #if defined(STXXL_BOOST_CONFIG) #include #include #endif #include __STXXL_BEGIN_NAMESPACE #ifndef STXXL_HAVE_SHARED_PTR #define STXXL_HAVE_SHARED_PTR 1 #endif #ifndef STXXL_HAVE_MAKE_SHARED #define STXXL_HAVE_MAKE_SHARED 1 #endif namespace compat { #if defined(__GXX_EXPERIMENTAL_CXX0X__) using std::shared_ptr; using std::make_shared; using std::allocate_shared; #elif defined(STXXL_BOOST_CONFIG) using boost::shared_ptr; using boost::make_shared; using boost::allocate_shared; #elif defined(__GNUG__) && ((__GNUC__ * 10000 + __GNUC_MINOR__ * 100) >= 40200) \ && (!defined(__ICC) || (__ICC >= 1100)) using std::tr1::shared_ptr; #undef STXXL_HAVE_MAKE_SHARED #define STXXL_HAVE_MAKE_SHARED 0 #else // no shared_ptr implementation available #undef STXXL_HAVE_SHARED_PTR #define STXXL_HAVE_SHARED_PTR 0 #undef STXXL_HAVE_MAKE_SHARED #define STXXL_HAVE_MAKE_SHARED 0 #endif } // namespace compat __STXXL_END_NAMESPACE #endif // !STXXL_HEADER__COMPAT__SHARED_PTR_H_ // vim: et:ts=4:sw=4 stxxl-1.3.1/include/stxxl/bits/compat/type_traits.h0000644000175000017500000000463511535654452022305 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/compat/type_traits.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2009-2011 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_HEADER__COMPAT_TYPE_TRAITS_H_ #define STXXL_HEADER__COMPAT_TYPE_TRAITS_H_ #if defined(__GXX_EXPERIMENTAL_CXX0X__) #include #elif defined(__GNUG__) && (__GNUC__ >= 4) #include #elif defined(STXXL_BOOST_CONFIG) #include #endif #include __STXXL_BEGIN_NAMESPACE namespace compat { #if defined(__GXX_EXPERIMENTAL_CXX0X__) using std::remove_const; #elif defined(__GNUG__) && (__GNUC__ >= 4) using std::tr1::remove_const; #elif defined(STXXL_BOOST_CONFIG) using boost::remove_const; #else template struct remove_const { typedef _Tp type; }; template struct remove_const<_Tp const> { typedef _Tp type; }; #endif #if defined(__GNUG__) && ((__GNUC__ * 10000 + __GNUC_MINOR__ * 100) < 40300) // That is a small subset of what GCC 4.3 does: // Utility for finding the signed versions of unsigned integral types. template struct __make_signed { typedef _Tp __type; }; template <> struct __make_signed { typedef signed char __type; }; template <> struct __make_signed { typedef signed char __type; }; template <> struct __make_signed { typedef signed short __type; }; template <> struct __make_signed { typedef signed int __type; }; template <> struct __make_signed { typedef signed long __type; }; template <> struct __make_signed { typedef signed long long __type; }; template struct make_signed { typedef typename __make_signed<_Tp>::__type type; }; #endif } // namespace compat __STXXL_END_NAMESPACE #endif // !STXXL_HEADER__COMPAT_TYPE_TRAITS_H_ stxxl-1.3.1/include/stxxl/bits/compat_unique_ptr.h0000644000175000017500000000340511260745605022177 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/compat_unique_ptr.h * * compatibility interface to unique_ptr (C++0x), previously auto_ptr * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2008 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_HEADER__COMPAT_UNIQUE_PTR_H_ #define STXXL_HEADER__COMPAT_UNIQUE_PTR_H_ #include #include __STXXL_BEGIN_NAMESPACE template struct compat_unique_ptr { #if defined(__GXX_EXPERIMENTAL_CXX0X__) && ((__GNUC__ * 10000 + __GNUC_MINOR__ * 100) >= 40400) typedef std::unique_ptr<_Tp> result; #else // auto_ptr is inherently broken and is deprecated by unique_ptr in c++0x typedef std::auto_ptr<_Tp> result; #endif }; __STXXL_END_NAMESPACE #if defined(__GNUG__) && ((__GNUC__ * 10000 + __GNUC_MINOR__ * 100) == 30400) namespace workaround_gcc_3_4 { // std::swap in gcc 3.4 is broken, __tmp is declared const there template inline void swap(_Tp & __a, _Tp & __b) { // concept requirements __glibcxx_function_requires(_SGIAssignableConcept<_Tp>) _Tp __tmp = __a; __a = __b; __b = __tmp; } } namespace std { // overload broken std::swap to call a working swap() template inline void swap(std::auto_ptr<_Tp> & a, std::auto_ptr<_Tp> & b) { workaround_gcc_3_4::swap(a, b); } } #endif #endif // !STXXL_HEADER__COMPAT_UNIQUE_PTR_H_ stxxl-1.3.1/include/stxxl/bits/deprecated.h0000644000175000017500000000175111513572701020537 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/deprecated.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2008-2009 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_HEADER__DEPRECATED_H #define STXXL_HEADER__DEPRECATED_H #ifdef STXXL_BOOST_CONFIG #include #endif #ifdef BOOST_MSVC #define _STXXL_DEPRECATED(x) __declspec(deprecated) x #elif defined(__GNUG__) && ((__GNUC__ * 10000 + __GNUC_MINOR__ * 100) < 30400) // no __attribute__ ((__deprecated__)) in GCC 3.3 #define _STXXL_DEPRECATED(x) x #else #define _STXXL_DEPRECATED(x) x __attribute__ ((__deprecated__)) #endif #endif // !STXXL_HEADER__DEPRECATED_H // vim: et:ts=4:sw=4 stxxl-1.3.1/include/stxxl/bits/msvc_compatibility.h0000644000175000017500000000204211533723736022342 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/msvc_compatibility.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2009, 2011 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_MSVC_COMPATIBILITY_H #define STXXL_MSVC_COMPATIBILITY_H #ifdef STXXL_BOOST_CONFIG #include #endif #ifdef BOOST_MSVC #include inline double log2(double x) { return (log(x) / log(2.)); } // http://msdn.microsoft.com/en-us/library/2ts7cx93.aspx #define snprintf _snprintf // http://msdn.microsoft.com/en-us/library/h80404d3.aspx #define strtoll _strtoi64 // http://msdn.microsoft.com/en-us/library/85zk715d.aspx #define strtoull _strtoui64 #endif #endif // !STXXL_MSVC_COMPATIBILITY_H // vim: et:ts=4:sw=4 stxxl-1.3.1/include/stxxl/bits/common/0000755000175000017500000000000011536252421017551 5ustar andreasandreasstxxl-1.3.1/include/stxxl/bits/common/tuple.h0000644000175000017500000001702611026753412021061 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/common/tuple.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2003 Roman Dementiev * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_TUPLE_HEADER #define STXXL_TUPLE_HEADER #include #include __STXXL_BEGIN_NAMESPACE struct Plug { }; template struct tuple_base { typedef T1 first_type; typedef T2 second_type; typedef T3 third_type; typedef T4 fourth_type; typedef T5 fifth_type; typedef T6 sixth_type; template struct item_type { /* typedef typename SWITCH > > > > > > >::result result; */ }; }; //! \brief k-Tuple data type //! //! (defined for k < 7) template struct tuple { typedef T1 first_type; typedef T2 second_type; typedef T3 third_type; typedef T4 fourth_type; typedef T5 fifth_type; typedef T6 sixth_type; template struct item_type { typedef typename SWITCH > > > > > > >::result result; }; //! \brief First tuple component first_type first; //! \brief Second tuple component second_type second; //! \brief Third tuple component third_type third; //! \brief Fourth tuple component fourth_type fourth; //! \brief Fifth tuple component fifth_type fifth; //! \brief Sixth tuple component sixth_type sixth; tuple() { } tuple(first_type fir, second_type sec, third_type thi, fourth_type fou, fifth_type fif, sixth_type six ) : first(fir), second(sec), third(thi), fourth(fou), fifth(fif), sixth(six) { } }; //! \brief Partial specialization for 1- \c tuple template struct tuple { typedef T1 first_type; first_type first; template struct item_type { typedef typename IF::result result; }; tuple() { } tuple(first_type fi) : first(fi) { } }; //! \brief Partial specialization for 2- \c tuple (equivalent to std::pair) template struct tuple { typedef T1 first_type; typedef T2 second_type; template struct item_type { typedef typename SWITCH > > >::result result; }; first_type first; second_type second; tuple() { } tuple(first_type fi, second_type se ) : first(fi), second(se) { } }; //! \brief Partial specialization for 3- \c tuple (triple) template struct tuple { typedef T1 first_type; typedef T2 second_type; typedef T3 third_type; template struct item_type { typedef typename SWITCH > > > >::result result; }; first_type first; second_type second; third_type third; tuple() { } tuple(first_type fir, second_type sec, third_type thi ) : first(fir), second(sec), third(thi) { } }; //! \brief Partial specialization for 4- \c tuple template struct tuple { typedef T1 first_type; typedef T2 second_type; typedef T3 third_type; typedef T4 fourth_type; template struct item_type { typedef typename SWITCH > > > > >::result result; }; first_type first; second_type second; third_type third; fourth_type fourth; tuple() { } tuple(first_type fir, second_type sec, third_type thi, fourth_type fou ) : first(fir), second(sec), third(thi), fourth(fou) { } }; //! \brief Partial specialization for 5- \c tuple template struct tuple { typedef T1 first_type; typedef T2 second_type; typedef T3 third_type; typedef T4 fourth_type; typedef T5 fifth_type; template struct item_type { typedef typename SWITCH > > > > > >::result result; }; first_type first; second_type second; third_type third; fourth_type fourth; fifth_type fifth; tuple() { } tuple(first_type fir, second_type sec, third_type thi, fourth_type fou, fifth_type fif ) : first(fir), second(sec), third(thi), fourth(fou), fifth(fif) { } }; /* template typename tuple_type::item_type::result get(const tuple_type & t) { return NULL; } */ __STXXL_END_NAMESPACE #endif // !STXXL_TUPLE_HEADER stxxl-1.3.1/include/stxxl/bits/common/is_sorted.h0000644000175000017500000000346411050141255021715 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/common/is_sorted.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2002 Roman Dementiev * Copyright (C) 2008 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_IS_SORTED_HEADER #define STXXL_IS_SORTED_HEADER #include __STXXL_BEGIN_NAMESPACE template bool is_sorted_helper(_ForwardIter __first, _ForwardIter __last) { if (__first == __last) return true; _ForwardIter __next = __first; for (++__next; __next != __last; __first = __next, ++__next) { if (*__next < *__first) return false; } return true; } template bool is_sorted_helper(_ForwardIter __first, _ForwardIter __last, _StrictWeakOrdering __comp) { if (__first == __last) return true; _ForwardIter __next = __first; for (++__next; __next != __last; __first = __next, ++__next) { if (__comp(*__next, *__first)) return false; } return true; } template bool is_sorted(_ForwardIter __first, _ForwardIter __last) { return is_sorted_helper(__first, __last); } template bool is_sorted(_ForwardIter __first, _ForwardIter __last, _StrictWeakOrdering __comp) { return is_sorted_helper(__first, __last, __comp); } __STXXL_END_NAMESPACE #endif // !STXXL_IS_SORTED_HEADER stxxl-1.3.1/include/stxxl/bits/common/error_handling.h0000644000175000017500000000703611531237734022732 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/common/error_handling.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2007-2010 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_ERROR_HANDLING_HEADER #define STXXL_ERROR_HANDLING_HEADER #include #include #include #include #include __STXXL_BEGIN_NAMESPACE #define _STXXL_STRING(x) # x #ifdef BOOST_MSVC #define STXXL_PRETTY_FUNCTION_NAME __FUNCTION__ #else #define STXXL_PRETTY_FUNCTION_NAME __PRETTY_FUNCTION__ #endif //////////////////////////////////////////////////////////////////////////// #define STXXL_THROW(exception_type, location, error_message) \ do { \ std::ostringstream msg_; \ msg_ << "Error in " << location << ": " << error_message; \ throw exception_type(msg_.str()); \ } while (false) #define STXXL_THROW2(exception_type, error_message) \ STXXL_THROW(exception_type, "function " << STXXL_PRETTY_FUNCTION_NAME, \ "Info: " << error_message << " " << strerror(errno)) #define STXXL_THROW_INVALID_ARGUMENT(error_message) \ STXXL_THROW(std::invalid_argument, \ "function " << STXXL_PRETTY_FUNCTION_NAME, \ error_message) #define STXXL_THROW_UNREACHABLE() \ STXXL_THROW(stxxl::unreachable, \ "file: " << __FILE__ << ", line: " << __LINE__, \ "must be unreachable code") //////////////////////////////////////////////////////////////////////////// template inline void stxxl_util_function_error(const char * func_name, const char * expr = 0, const char * error = 0) { std::ostringstream str_; str_ << "Error in function " << func_name << " " << (expr ? expr : strerror(errno)); if (error) str_ << " " << error; throw E(str_.str()); } #define stxxl_function_error(exception_type) \ stxxl::stxxl_util_function_error(STXXL_PRETTY_FUNCTION_NAME) template inline bool helper_check_success(bool success, const char * func_name, const char * expr = 0, const char * error = 0) { if (!success) stxxl_util_function_error(func_name, expr, error); return success; } template inline bool helper_check_eq_0(INT res, const char * func_name, const char * expr, bool res_2_strerror = false) { return helper_check_success(res == 0, func_name, expr, res_2_strerror ? strerror(res) : 0); } #define check_pthread_call(expr) \ stxxl::helper_check_eq_0(expr, STXXL_PRETTY_FUNCTION_NAME, _STXXL_STRING(expr), true) template inline bool helper_check_ge_0(INT res, const char * func_name) { return helper_check_success(res >= 0, func_name); } #define stxxl_check_ge_0(expr, exception_type) \ stxxl::helper_check_ge_0(expr, STXXL_PRETTY_FUNCTION_NAME) template inline bool helper_check_ne_0(INT res, const char * func_name) { return helper_check_success(res != 0, func_name); } #define stxxl_check_ne_0(expr, exception_type) \ stxxl::helper_check_ne_0(expr, STXXL_PRETTY_FUNCTION_NAME) __STXXL_END_NAMESPACE #endif // !STXXL_ERROR_HANDLING_HEADER stxxl-1.3.1/include/stxxl/bits/common/utils.h0000644000175000017500000001057211535404612021067 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/common/utils.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2002-2006 Roman Dementiev * Copyright (C) 2007-2009 Andreas Beckmann * Copyright (C) 2008 Johannes Singler * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_UTILS_HEADER #define STXXL_UTILS_HEADER #include #include #include #include #ifdef STXXL_BOOST_CONFIG #include #endif #include #include #include #include __STXXL_BEGIN_NAMESPACE //////////////////////////////////////////////////////////////////////////// #if defined(__GXX_EXPERIMENTAL_CXX0X__) #define STXXL_STATIC_ASSERT(x) static_assert(x, #x) #else #define STXXL_STATIC_ASSERT(x) { typedef int static_assert_dummy_type[(x) ? 1 : -1]; } #endif //////////////////////////////////////////////////////////////////////////// inline std::vector split(const std::string & str, const std::string & sep) { std::vector result; if (str.empty()) return result; std::string::size_type CurPos(0), LastPos(0); while (1) { CurPos = str.find(sep, LastPos); if (CurPos == std::string::npos) break; std::string sub = str.substr(LastPos, std::string::size_type(CurPos - LastPos)); if (sub.size()) result.push_back(sub); LastPos = CurPos + sep.size(); } std::string sub = str.substr(LastPos); if (sub.size()) result.push_back(sub); return result; } //////////////////////////////////////////////////////////////////////////// inline stxxl::int64 atoint64(const char * s) { #ifdef BOOST_MSVC return _atoi64(s); #else return atoll(s); #endif } //////////////////////////////////////////////////////////////////////////// template inline const Tp & STXXL_MIN(const Tp & a, const Tp & b) { return std::min(a, b); } template inline const Tp & STXXL_MAX(const Tp & a, const Tp & b) { return std::max(a, b); } //////////////////////////////////////////////////////////////////////////// template inline Integral log2_ceil(Integral i) { return Integral(ceil(log2(i))); } template inline Integral log2_floor(Integral i) { return Integral(log2(i)); } //////////////////////////////////////////////////////////////////////////// template inline typename compat::remove_const::type div_ceil(Integral __n, Integral2 __d) { #if 0 // ambiguous overload for std::div(unsigned_anything, unsigned_anything) typedef __typeof__(std::div(__n, __d)) div_type; div_type result = std::div(__n, __d); return result.quot + (result.rem != 0); #else return __n / __d + ((__n % __d) != 0); #endif } //////////////////////////////////////////////////////////////////////////// #ifdef __GNUC__ #define HAVE_BUILTIN_EXPECT #endif #ifdef HAVE_BUILTIN_EXPECT #define LIKELY(c) __builtin_expect((c), 1) #else #define LIKELY(c) c #endif #ifdef HAVE_BUILTIN_EXPECT #define UNLIKELY(c) __builtin_expect((c), 0) #else #define UNLIKELY(c) c #endif //////////////////////////////////////////////////////////////////////////// inline uint64 longhash1(uint64 key_) { key_ += ~(key_ << 32); key_ ^= (key_ >> 22); key_ += ~(key_ << 13); key_ ^= (key_ >> 8); key_ += (key_ << 3); key_ ^= (key_ >> 15); key_ += ~(key_ << 27); key_ ^= (key_ >> 31); return key_; } //////////////////////////////////////////////////////////////////////////// template inline void swap_1D_arrays(T * a, T * b, unsigned_type size) { for (unsigned_type i = 0; i < size; ++i) std::swap(a[i], b[i]); } //////////////////////////////////////////////////////////////////////////// __STXXL_END_NAMESPACE #endif // !STXXL_UTILS_HEADER // vim: et:ts=4:sw=4 stxxl-1.3.1/include/stxxl/bits/common/settings.h0000644000175000017500000000170711026753412021567 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/common/settings.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2007 Johannes Singler * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ /** * @file settings.h * @brief Provides a static class to store runtime tuning parameters. */ #ifndef STXXL_SETTINGS_HEADER #define STXXL_SETTINGS_HEADER #include __STXXL_BEGIN_NAMESPACE template class settings { public: static bool native_merge; }; template bool settings::native_merge = true; typedef settings<> SETTINGS; __STXXL_END_NAMESPACE #endif // !STXXL_SETTINGS_HEADER stxxl-1.3.1/include/stxxl/bits/common/switch.h0000644000175000017500000000670111270157465021236 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/common/switch.h * * kind of semaphore * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2002 Roman Dementiev * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_SWITCH_HEADER #define STXXL_SWITCH_HEADER #ifdef STXXL_BOOST_THREADS #include #include #else #include #endif #include #include __STXXL_BEGIN_NAMESPACE //#define onoff_switch Switch class onoff_switch : private noncopyable { #ifdef STXXL_BOOST_THREADS boost::mutex mutex; boost::condition cond; #else pthread_mutex_t mutex; pthread_cond_t cond; #endif bool _on; public: onoff_switch(bool flag = false) : _on(flag) { #ifndef STXXL_BOOST_THREADS check_pthread_call(pthread_mutex_init(&mutex, NULL)); check_pthread_call(pthread_cond_init(&cond, NULL)); #endif } ~onoff_switch() { #ifndef STXXL_BOOST_THREADS int res = pthread_mutex_trylock(&mutex); if (res == 0 || res == EBUSY) { check_pthread_call(pthread_mutex_unlock(&mutex)); } else stxxl_function_error(resource_error); check_pthread_call(pthread_mutex_destroy(&mutex)); check_pthread_call(pthread_cond_destroy(&cond)); #endif } void on() { #ifdef STXXL_BOOST_THREADS boost::mutex::scoped_lock Lock(mutex); _on = true; Lock.unlock(); cond.notify_one(); #else check_pthread_call(pthread_mutex_lock(&mutex)); _on = true; check_pthread_call(pthread_mutex_unlock(&mutex)); check_pthread_call(pthread_cond_signal(&cond)); #endif } void off() { #ifdef STXXL_BOOST_THREADS boost::mutex::scoped_lock Lock(mutex); _on = false; Lock.unlock(); cond.notify_one(); #else check_pthread_call(pthread_mutex_lock(&mutex)); _on = false; check_pthread_call(pthread_mutex_unlock(&mutex)); check_pthread_call(pthread_cond_signal(&cond)); #endif } void wait_for_on() { #ifdef STXXL_BOOST_THREADS boost::mutex::scoped_lock Lock(mutex); if (!_on) cond.wait(Lock); #else check_pthread_call(pthread_mutex_lock(&mutex)); if (!_on) check_pthread_call(pthread_cond_wait(&cond, &mutex)); check_pthread_call(pthread_mutex_unlock(&mutex)); #endif } void wait_for_off() { #ifdef STXXL_BOOST_THREADS boost::mutex::scoped_lock Lock(mutex); if (_on) cond.wait(Lock); #else check_pthread_call(pthread_mutex_lock(&mutex)); if (_on) check_pthread_call(pthread_cond_wait(&cond, &mutex)); check_pthread_call(pthread_mutex_unlock(&mutex)); #endif } bool is_on() { #ifdef STXXL_BOOST_THREADS boost::mutex::scoped_lock Lock(mutex); return _on; #else bool res; check_pthread_call(pthread_mutex_lock(&mutex)); res = _on; check_pthread_call(pthread_mutex_unlock(&mutex)); return res; #endif } }; __STXXL_END_NAMESPACE #endif // !STXXL_SWITCH_HEADER stxxl-1.3.1/include/stxxl/bits/common/mutex.h0000644000175000017500000000433611123517350021067 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/common/mutex.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2002 Roman Dementiev * Copyright (C) 2008 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_MUTEX_HEADER #define STXXL_MUTEX_HEADER #include #ifdef STXXL_BOOST_THREADS #include #else #include #include #include #include #endif __STXXL_BEGIN_NAMESPACE #ifdef STXXL_BOOST_THREADS typedef boost::mutex mutex; #else class mutex : private noncopyable { pthread_mutex_t _mutex; public: mutex() { check_pthread_call(pthread_mutex_init(&_mutex, NULL)); } ~mutex() { int res = pthread_mutex_trylock(&_mutex); if (res == 0 || res == EBUSY) { check_pthread_call(pthread_mutex_unlock(&_mutex)); } else stxxl_function_error(resource_error); check_pthread_call(pthread_mutex_destroy(&_mutex)); } void lock() { check_pthread_call(pthread_mutex_lock(&_mutex)); } void unlock() { check_pthread_call(pthread_mutex_unlock(&_mutex)); } }; #endif #ifdef STXXL_BOOST_THREADS typedef boost::mutex::scoped_lock scoped_mutex_lock; #else //! \brief Aquire a lock that's valid until the end of scope class scoped_mutex_lock { mutex & mtx; bool is_locked; public: scoped_mutex_lock(mutex & mtx_) : mtx(mtx_), is_locked(false) { lock(); } ~scoped_mutex_lock() { unlock(); } void lock() { if (!is_locked) { mtx.lock(); is_locked = true; } } void unlock() { if (is_locked) { mtx.unlock(); is_locked = false; } } }; #endif __STXXL_END_NAMESPACE #endif // !STXXL_MUTEX_HEADER stxxl-1.3.1/include/stxxl/bits/common/new_alloc.h0000644000175000017500000000724111513611117021665 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/common/new_alloc.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2002-2006 Roman Dementiev * Copyright (C) 2007, 2008, 2010 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_NEW_ALLOC_HEADER #define STXXL_NEW_ALLOC_HEADER #include #include #include __STXXL_BEGIN_NAMESPACE template class new_alloc; template struct new_alloc_rebind; template struct new_alloc_rebind{ typedef new_alloc other; }; template struct new_alloc_rebind { typedef std::allocator other; }; // designed for typed_block (to use with std::vector) template class new_alloc { public: // type definitions typedef T value_type; typedef T * pointer; typedef const T * const_pointer; typedef T & reference; typedef const T & const_reference; typedef std::size_t size_type; typedef std::ptrdiff_t difference_type; // rebind allocator to type U, use new_alloc only if U == T template struct rebind { typedef typename new_alloc_rebind::other other; }; // return address of values pointer address(reference value) const { return &value; } const_pointer address(const_reference value) const { return &value; } new_alloc() throw () { } new_alloc(const new_alloc &) throw () { } template new_alloc(const new_alloc &) throw () { } ~new_alloc() throw () { } template operator std::allocator() { static std::allocator helper_allocator; return helper_allocator; } // return maximum number of elements that can be allocated size_type max_size() const throw () { return (std::numeric_limits::max)() / sizeof(T); } // allocate but don't initialize num elements of type T pointer allocate(size_type num, const void * = 0) { return static_cast(T::operator new (num * sizeof(T))); } // _GLIBCXX_RESOLVE_LIB_DEFECTS // 402. wrong new expression in [some_] allocator::construct // initialize elements of allocated storage p with value value void construct(pointer p, const T & value) { // initialize memory with placement new ::new ((void *)p)T(value); } #ifdef __GXX_EXPERIMENTAL_CXX0X__ template void construct(pointer p, Args && ... args) { ::new ((void *)p)T(std::forward(args) ...); } #endif // destroy elements of initialized storage p void destroy(pointer p) { // destroy objects by calling their destructor p->~T(); } // deallocate storage p of deleted elements void deallocate(pointer p, size_type /*num*/) { T::operator delete (p); } }; // return that all specializations of this allocator are interchangeable template inline bool operator == (const new_alloc &, const new_alloc &) throw () { return true; } template inline bool operator != (const new_alloc &, const new_alloc &) throw () { return false; } __STXXL_END_NAMESPACE #endif // !STXXL_NEW_ALLOC_HEADER // vim: et:ts=4:sw=4 stxxl-1.3.1/include/stxxl/bits/common/types.h0000644000175000017500000000331711513611117021066 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/common/types.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2007 Roman Dementiev * Copyright (C) 2010 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_TYPES_HEADER #define STXXL_TYPES_HEADER #ifdef STXXL_BOOST_CONFIG #include #endif #include __STXXL_BEGIN_NAMESPACE #ifdef STXXL_BOOST_CONFIG #ifdef BOOST_MSVC typedef __int64 int64; typedef unsigned __int64 uint64; #else typedef long long int int64; typedef unsigned long long int uint64; #endif #else typedef long long int int64; typedef unsigned long long int uint64; #endif // integer types declarations enum { my_pointer_size = sizeof(void *) }; template struct choose_int_types { }; template <> struct choose_int_types<4> // for 32-bit processors/compilers { typedef int int_type; typedef unsigned unsigned_type; }; template <> struct choose_int_types<8> // for 64-bit processors/compilers { typedef int64 int_type; typedef uint64 unsigned_type; }; typedef choose_int_types::int_type int_type; typedef choose_int_types::unsigned_type unsigned_type; typedef unsigned_type internal_size_type; // fits in internal memory typedef uint64 external_size_type; // may require external memory __STXXL_END_NAMESPACE #endif // !STXXL_TYPES_HEADER stxxl-1.3.1/include/stxxl/bits/common/exithandler.h0000644000175000017500000000253511260745605022243 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/common/exithandler.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2009 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_EXITHANDLER_HEADER #define STXXL_EXITHANDLER_HEADER #include __STXXL_BEGIN_NAMESPACE // There are several possibilities for the exit handlers. // To use the default implementation (which uses atexit()), nothing special has to be done. // // To work around problems with atexit() being used in a dll you may #define STXXL_NON_DEFAULT_EXIT_HANDLER at library compilation time. // In this case the library/application should call stxxl::run_exit_handlers() during shutdown. // // To provide your own exit handler implementation, #define STXXL_EXTERNAL_EXIT_HANDLER and implement // stxxl::register_exit_handler(void (*)(void)) and stxxl::run_exit_handlers() in your application. int register_exit_handler(void (* function)(void)); void run_exit_handlers(); __STXXL_END_NAMESPACE #endif // !STXXL_EXITHANDLER_HEADER // vim: et:ts=4:sw=4 stxxl-1.3.1/include/stxxl/bits/common/tmeta.h0000644000175000017500000000570711531237734021052 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/common/tmeta.h * * Template Metaprogramming Tools * (from the Generative Programming book Krysztof Czarnecki, Ulrich Eisenecker) * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2003 Roman Dementiev * Copyright (C) 2008 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_META_TEMPLATE_PROGRAMMING #define STXXL_META_TEMPLATE_PROGRAMMING #include #include __STXXL_BEGIN_NAMESPACE //! \brief IF template metaprogramming statement //! If \c Flag is \c true then \c IF<>::result is of type Type1 //! otherwise of \c IF<>::result is of type Type2 template struct IF { typedef Type1 result; }; template struct IF { typedef Type2 result; }; //! If \c Flag is \c true then \c IF<>::result is Num1 //! otherwise of \c IF<>::result is Num2 template struct IF_N { enum { result = Num1 }; }; template struct IF_N { enum { result = Num2 }; }; const int DEFAULT = ~(~0u >> 1); // initialize with the smallest int struct NilCase { }; template struct CASE { enum { tag = tag_ }; typedef Type_ Type; typedef Next_ Next; }; template class SWITCH { typedef typename Case::Next NextCase; enum { caseTag = Case::tag, found = (caseTag == tag || caseTag == DEFAULT) }; public: typedef typename IF::result >::result result; }; template class SWITCH { public: typedef NilCase result; }; //! \internal, use LOG2 instead template class LOG2_floor { public: enum { value = LOG2_floor::value + 1 }; }; template <> class LOG2_floor<1> { public: enum { value = 0 }; }; template <> class LOG2_floor<0> { public: enum { value = 0 }; }; template class LOG2 { public: enum { floor = LOG2_floor::value, ceil = LOG2_floor::value + 1 }; }; template <> class LOG2<1> { public: enum { floor = 0, ceil = 0 }; }; template <> class LOG2<0> { public: enum { floor = 0, ceil = 0 }; }; __STXXL_END_NAMESPACE #endif // !STXXL_META_TEMPLATE_PROGRAMMING stxxl-1.3.1/include/stxxl/bits/common/simple_vector.h0000644000175000017500000000473111535423034022601 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/common/simple_vector.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2002 Roman Dementiev * Copyright (C) 2008, 2011 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_SIMPLE_VECTOR_HEADER #define STXXL_SIMPLE_VECTOR_HEADER #include #include #include __STXXL_BEGIN_NAMESPACE template class simple_vector : private noncopyable { public: typedef unsigned_type size_type; typedef _Tp value_type; // typedef simple_alloc<_Tp, _Alloc> _data_allocator; protected: size_type _size; value_type * _array; public: typedef value_type * iterator; typedef const value_type * const_iterator; typedef value_type & reference; typedef const value_type & const_reference; simple_vector(size_type sz) : _size(sz), _array(NULL) { // _array = _data_allocator.allocate(sz); if (size() > 0) _array = new _Tp[size()]; } void swap(simple_vector & obj) { std::swap(_size, obj._size); std::swap(_array, obj._array); } ~simple_vector() { // _data_allocator.deallocate(_array,_size); delete[] _array; } iterator begin() { return _array; } const_iterator begin() const { return _array; } const_iterator cbegin() const { return begin(); } iterator end() { return _array + _size; } const_iterator end() const { return _array + _size; } const_iterator cend() const { return end(); } size_type size() const { return _size; } reference operator [] (size_type i) { return *(begin() + i); } const_reference operator [] (size_type i) const { return *(begin() + i); } }; __STXXL_END_NAMESPACE namespace std { template void swap(stxxl::simple_vector & a, stxxl::simple_vector & b) { a.swap(b); } } #endif // !STXXL_SIMPLE_VECTOR_HEADER stxxl-1.3.1/include/stxxl/bits/common/aligned_alloc.h0000644000175000017500000001214511421322641022475 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/common/aligned_alloc.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2002 Roman Dementiev * Copyright (C) 2009 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_ALIGNED_ALLOC #define STXXL_ALIGNED_ALLOC #include #include #include #include #ifndef STXXL_VERBOSE_ALIGNED_ALLOC #define STXXL_VERBOSE_ALIGNED_ALLOC STXXL_VERBOSE2 #endif __STXXL_BEGIN_NAMESPACE template struct aligned_alloc_settings { static bool may_use_realloc; }; template bool aligned_alloc_settings::may_use_realloc = true; // meta_info_size > 0 is needed for array allocations that have overhead // // meta_info // aligned begin of data unallocated behind data // v v v // ----===============#MMMM========================------ // ^ ^^ ^ // buffer result result+m_i_size+size // pointer to buffer // (---) unallocated, (===) allocated memory template inline void * aligned_alloc(size_t size, size_t meta_info_size = 0) { STXXL_VERBOSE2("stxxl::aligned_alloc<" << ALIGNMENT << ">(), size = " << size << ", meta info size = " << meta_info_size); #if !defined(STXXL_WASTE_MORE_MEMORY_FOR_IMPROVED_ACCESS_AFTER_ALLOCATED_MEMORY_CHECKS) // malloc()/realloc() variant that frees the unused amount of memory // after the data area of size 'size'. realloc() from valgrind does not // preserve the old memory area when shrinking, so out-of-bounds // accesses can't be detected easily. // Overhead: about ALIGNMENT bytes. size_t alloc_size = ALIGNMENT + sizeof(char *) + meta_info_size + size; char * buffer = (char *)std::malloc(alloc_size); #else // More space consuming and memory fragmenting variant using // posix_memalign() instead of malloc()/realloc(). Ensures that the end // of the data area (of size 'size') will match the end of the allocated // block, so no corrections are neccessary and // access-behind-allocated-memory problems can be easily detected by // valgrind. Usually produces an extra memory fragment of about // ALIGNMENT bytes. // Overhead: about 2 * ALIGNMENT bytes. size_t alloc_size = ALIGNMENT * div_ceil(sizeof(char *) + meta_info_size, ALIGNMENT) + size; char * buffer; if (posix_memalign((void **)&buffer, ALIGNMENT, alloc_size) != 0) throw std::bad_alloc(); #endif if (buffer == NULL) throw std::bad_alloc(); #ifdef STXXL_ALIGNED_CALLOC memset(buffer, 0, alloc_size); #endif char * reserve_buffer = buffer + sizeof(char *) + meta_info_size; char * result = reserve_buffer + ALIGNMENT - (((unsigned long)reserve_buffer) % (ALIGNMENT)) - meta_info_size; STXXL_VERBOSE2("stxxl::aligned_alloc<" << ALIGNMENT << ">() address " << (void *)result << " lost " << (result - buffer) << " bytes"); assert(long(result - buffer) >= long(sizeof(char *))); // free unused memory behind the data area // so access behind the requested size can be recognized size_t realloc_size = (result - buffer) + meta_info_size + size; if (realloc_size < alloc_size && aligned_alloc_settings::may_use_realloc) { char * realloced = (char *)std::realloc(buffer, realloc_size); if (buffer != realloced) { // hmm, realloc does move the memory block around while shrinking, // might run under valgrind, so disable realloc and retry STXXL_ERRMSG("stxxl::aligned_alloc: disabling realloc()"); std::free(realloced); aligned_alloc_settings::may_use_realloc = false; return aligned_alloc(size, meta_info_size); } assert(result + size <= buffer + realloc_size); } *(((char **)result) - 1) = buffer; STXXL_VERBOSE2("stxxl::aligned_alloc<" << ALIGNMENT << ">(), allocated at " << (void *)buffer << " returning " << (void *)result); STXXL_VERBOSE_ALIGNED_ALLOC("stxxl::aligned_alloc<" << ALIGNMENT << ">(size = " << size << ", meta info size = " << meta_info_size << ") => buffer = " << (void *)buffer << ", ptr = " << (void *)result); return result; } template inline void aligned_dealloc(void * ptr) { if (!ptr) return; char * buffer = *(((char **)ptr) - 1); STXXL_VERBOSE_ALIGNED_ALLOC("stxxl::aligned_dealloc<" << ALIGNMENT << ">(), ptr = " << ptr << ", buffer = " << (void *)buffer); std::free(buffer); } __STXXL_END_NAMESPACE #endif // !STXXL_ALIGNED_ALLOC // vim: et:ts=4:sw=4 stxxl-1.3.1/include/stxxl/bits/common/seed.h0000644000175000017500000000154411026753412020646 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/common/seed.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2007 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_SEED_HEADER #define STXXL_SEED_HEADER #include __STXXL_BEGIN_NAMESPACE //! \brief set the global stxxl seed value void set_seed(unsigned seed); //! \brief get a seed value for prng initialization, //! subsequent calls return a sequence of different values unsigned get_next_seed(); __STXXL_END_NAMESPACE #endif // !STXXL_SEED_HEADER stxxl-1.3.1/include/stxxl/bits/common/state.h0000644000175000017500000000562011531445437021053 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/common/state.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2002 Roman Dementiev * Copyright (C) 2008 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_STATE_HEADER #define STXXL_STATE_HEADER #ifdef STXXL_BOOST_THREADS #include #include #else #include #endif #include #include __STXXL_BEGIN_NAMESPACE template class state : private noncopyable { typedef Tp value_type; #ifdef STXXL_BOOST_THREADS boost::mutex mutex; boost::condition cond; #else pthread_mutex_t mutex; pthread_cond_t cond; #endif value_type _state; public: state(value_type s) : _state(s) { #ifndef STXXL_BOOST_THREADS check_pthread_call(pthread_mutex_init(&mutex, NULL)); check_pthread_call(pthread_cond_init(&cond, NULL)); #endif } ~state() { #ifndef STXXL_BOOST_THREADS int res = pthread_mutex_trylock(&mutex); if (res == 0 || res == EBUSY) { check_pthread_call(pthread_mutex_unlock(&mutex)); } else stxxl_function_error(resource_error); check_pthread_call(pthread_mutex_destroy(&mutex)); check_pthread_call(pthread_cond_destroy(&cond)); #endif } void set_to(value_type new_state) { #ifdef STXXL_BOOST_THREADS boost::mutex::scoped_lock Lock(mutex); _state = new_state; Lock.unlock(); cond.notify_all(); #else check_pthread_call(pthread_mutex_lock(&mutex)); _state = new_state; check_pthread_call(pthread_mutex_unlock(&mutex)); check_pthread_call(pthread_cond_broadcast(&cond)); #endif } void wait_for(value_type needed_state) { #ifdef STXXL_BOOST_THREADS boost::mutex::scoped_lock Lock(mutex); while (needed_state != _state) cond.wait(Lock); #else check_pthread_call(pthread_mutex_lock(&mutex)); while (needed_state != _state) check_pthread_call(pthread_cond_wait(&cond, &mutex)); check_pthread_call(pthread_mutex_unlock(&mutex)); #endif } value_type operator () () { #ifdef STXXL_BOOST_THREADS boost::mutex::scoped_lock Lock(mutex); return _state; #else value_type res; check_pthread_call(pthread_mutex_lock(&mutex)); res = _state; check_pthread_call(pthread_mutex_unlock(&mutex)); return res; #endif } }; __STXXL_END_NAMESPACE #endif // !STXXL_STATE_HEADER stxxl-1.3.1/include/stxxl/bits/common/timer.h0000644000175000017500000000552011531237734021051 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/common/timer.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2002, 2005 Roman Dementiev * Copyright (C) 2007-2009 Andreas Beckmann * Copyright (C) 2008 Johannes Singler * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_TIMER_HEADER #define STXXL_TIMER_HEADER #ifdef STXXL_BOOST_TIMESTAMP #include #include #else #include #include #endif #include __STXXL_BEGIN_NAMESPACE //! \brief Returns number of seconds since the epoch, high resolution. inline double timestamp() { #ifdef STXXL_BOOST_TIMESTAMP boost::posix_time::ptime MyTime = boost::posix_time::microsec_clock::local_time(); boost::posix_time::time_duration Duration = MyTime - boost::posix_time::time_from_string("1970-01-01 00:00:00.000"); double sec = double(Duration.hours()) * 3600. + double(Duration.minutes()) * 60. + double(Duration.seconds()) + double(Duration.fractional_seconds()) / (pow(10., Duration.num_fractional_digits())); return sec; #else struct timeval tp; gettimeofday(&tp, NULL); return double(tp.tv_sec) + tp.tv_usec / 1000000.; #endif } class timer { bool running; double accumulated; double last_clock; inline double timestamp(); public: inline timer(bool start_immediately = false); inline void start(); inline void stop(); inline void reset(); inline double seconds(); inline double mseconds(); inline double useconds(); }; timer::timer(bool start_immediately) : running(false), accumulated(0.) { if (start_immediately) start(); } double timer::timestamp() { return stxxl::timestamp(); } void timer::start() { running = true; last_clock = timestamp(); } void timer::stop() { running = false; accumulated += timestamp() - last_clock; } void timer::reset() { accumulated = 0.; last_clock = timestamp(); } double timer::mseconds() { if (running) return (accumulated + timestamp() - last_clock) * 1000.; return (accumulated * 1000.); } double timer::useconds() { if (running) return (accumulated + timestamp() - last_clock) * 1000000.; return (accumulated * 1000000.); } double timer::seconds() { if (running) return (accumulated + timestamp() - last_clock); return (accumulated); } __STXXL_END_NAMESPACE #endif // !STXXL_TIMER_HEADER // vim: et:ts=4:sw=4 stxxl-1.3.1/include/stxxl/bits/common/log.h0000644000175000017500000000236611535151017020510 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/common/log.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2004-2005 Roman Dementiev * Copyright (C) 2009 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_LOG_HEADER #define STXXL_LOG_HEADER #include #include #include #include __STXXL_BEGIN_NAMESPACE class logger : public singleton { friend class singleton; std::ofstream log_stream_; std::ofstream errlog_stream_; std::ofstream * waitlog_stream_; logger(); ~logger(); public: inline std::ofstream & log_stream() { return log_stream_; } inline std::ofstream & errlog_stream() { return errlog_stream_; } inline std::ofstream * waitlog_stream() { return waitlog_stream_; } }; __STXXL_END_NAMESPACE #endif // !STXXL_LOG_HEADER stxxl-1.3.1/include/stxxl/bits/common/exceptions.h0000644000175000017500000000363311267571321022114 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/common/exceptions.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2006 Roman Dementiev * Copyright (C) 2009 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_EXCEPTIONS_H_ #define STXXL_EXCEPTIONS_H_ #include #include #include #include __STXXL_BEGIN_NAMESPACE class io_error : public std::ios_base::failure { public: io_error() throw () : std::ios_base::failure("") { } io_error(const std::string & msg_) throw () : std::ios_base::failure(msg_) { } }; class resource_error : public std::runtime_error { public: resource_error() throw () : std::runtime_error("") { } resource_error(const std::string & msg_) throw () : std::runtime_error(msg_) { } }; class bad_ext_alloc : public std::runtime_error { public: bad_ext_alloc() throw () : std::runtime_error("") { } bad_ext_alloc(const std::string & msg_) throw () : std::runtime_error(msg_) { } }; class bad_parameter : public std::runtime_error { public: bad_parameter() throw () : std::runtime_error("") { } bad_parameter(const std::string & msg_) throw () : std::runtime_error(msg_) { } }; class unreachable : public std::runtime_error { public: unreachable() throw () : std::runtime_error("") { } unreachable(const std::string & msg_) throw () : std::runtime_error(msg_) { } }; __STXXL_END_NAMESPACE #endif // !STXXL_EXCEPTIONS_H_ // vim: et:ts=4:sw=4 stxxl-1.3.1/include/stxxl/bits/common/semaphore.h0000644000175000017500000000735511270157465021726 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/common/semaphore.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2002 Roman Dementiev * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_SEMAPHORE_HEADER #define STXXL_SEMAPHORE_HEADER #ifdef STXXL_BOOST_THREADS #include #include #else #include #endif #include #include __STXXL_BEGIN_NAMESPACE class semaphore : private noncopyable { int v; #ifdef STXXL_BOOST_THREADS boost::mutex mutex; boost::condition cond; #else pthread_mutex_t mutex; pthread_cond_t cond; #endif public: semaphore(int init_value = 1) : v(init_value) { #ifndef STXXL_BOOST_THREADS check_pthread_call(pthread_mutex_init(&mutex, NULL)); check_pthread_call(pthread_cond_init(&cond, NULL)); #endif } ~semaphore() { #ifndef STXXL_BOOST_THREADS int res = pthread_mutex_trylock(&mutex); if (res == 0 || res == EBUSY) { check_pthread_call(pthread_mutex_unlock(&mutex)); } else stxxl_function_error(resource_error); check_pthread_call(pthread_mutex_destroy(&mutex)); check_pthread_call(pthread_cond_destroy(&cond)); #endif } // function increments the semaphore and signals any threads that // are blocked waiting a change in the semaphore int operator ++ (int) { #ifdef STXXL_BOOST_THREADS boost::mutex::scoped_lock Lock(mutex); int res = ++v; Lock.unlock(); cond.notify_one(); #else check_pthread_call(pthread_mutex_lock(&mutex)); int res = ++v; check_pthread_call(pthread_mutex_unlock(&mutex)); check_pthread_call(pthread_cond_signal(&cond)); #endif return res; } // function decrements the semaphore and blocks if the semaphore is // <= 0 until another thread signals a change int operator -- (int) { #ifdef STXXL_BOOST_THREADS boost::mutex::scoped_lock Lock(mutex); while (v <= 0) cond.wait(Lock); int res = --v; #else check_pthread_call(pthread_mutex_lock(&mutex)); while (v <= 0) check_pthread_call(pthread_cond_wait(&cond, &mutex)); int res = --v; check_pthread_call(pthread_mutex_unlock(&mutex)); #endif return res; } // function does NOT block but simply decrements the semaphore // should not be used instead of down -- only for programs where // multiple threads must up on a semaphore before another thread // can go down, i.e., allows programmer to set the semaphore to // a negative value prior to using it for synchronization. int decrement() { #ifdef STXXL_BOOST_THREADS boost::mutex::scoped_lock Lock(mutex); return (--v); #else check_pthread_call(pthread_mutex_lock(&mutex)); int res = --v; check_pthread_call(pthread_mutex_unlock(&mutex)); return res; #endif } // function returns the value of the semaphore at the time the // critical section is accessed. obviously the value is not guaranteed // after the function unlocks the critical section. //int operator() //{ // check_pthread_call(pthread_mutex_lock(&mutex)); // int res = v; // check_pthread_call(pthread_mutex_unlock(&mutex)); // return res; //}; }; __STXXL_END_NAMESPACE #endif // !STXXL_SEMAPHORE_HEADER stxxl-1.3.1/include/stxxl/bits/common/rand.h0000644000175000017500000001161211026753412020647 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/common/rand.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2002, 2003, 2005 Roman Dementiev * Copyright (C) 2007 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_RAND_HEADER #define STXXL_RAND_HEADER #include #ifdef STXXL_BOOST_RANDOM #include #endif #include #include // Recommended seeding procedure: // by default, the global seed is initialized from a high resolution timer and the process id // 1. stxxl::set_seed(seed); // optionally, do this if you wan't to us a specific seed to replay a certain program run // 2. seed = stxxl::get_next_seed(); // store/print/... this value can be used for step 1 to replay the program with a specific seed // 3. stxxl::srandom_number32(); // seed the global state of stxxl::random_number32 // 4. create all the other prngs used. __STXXL_BEGIN_NAMESPACE extern unsigned ran32State; //! \brief Fast uniform [0, 2^32) pseudo-random generator //! with period 2^32, random bits: 32. //! \warning Uses a global state and is not reentrant or thread-safe! struct random_number32 { typedef unsigned value_type; //! \brief Returns a random number from [0, 2^32) inline value_type operator () () const { return (ran32State = 1664525 * ran32State + 1013904223); } }; //! \brief Set a seed value for \c random_number32. inline void srandom_number32(unsigned seed = 0) { if (!seed) seed = get_next_seed(); ran32State = seed; } //! \brief Fast uniform [0, 2^32) pseudo-random generator //! with period 2^32, random bits: 32. //! Reentrant variant of random_number32 that keeps it's private state. struct random_number32_r { typedef unsigned value_type; mutable unsigned state; random_number32_r(unsigned seed = 0) { if (!seed) seed = get_next_seed(); state = seed; } //! \brief Returns a random number from [0, 2^32) inline value_type operator () () const { return (state = 1664525 * state + 1013904223); } }; //! \brief Fast uniform [0.0, 1.0) pseudo-random generator //! \warning Uses a global state and is not reentrant or thread-safe! struct random_uniform_fast { typedef double value_type; random_number32 rnd32; random_uniform_fast(unsigned /*seed*/ = 0) { } //! \brief Returns a random number from [0.0, 1.0) inline value_type operator () () const { return (double(rnd32()) * (0.5 / 0x80000000)); } }; //! \brief Slow and precise uniform [0.0, 1.0) pseudo-random generator //! period: at least 2^48, random bits: at least 31 //! //! \warning Seed is not the same as in the fast generator \c random_uniform_fast struct random_uniform_slow { typedef double value_type; #ifdef STXXL_BOOST_RANDOM typedef boost::minstd_rand base_generator_type; base_generator_type generator; boost::uniform_real<> uni_dist; mutable boost::variate_generator > uni; random_uniform_slow(unsigned seed = 0) : uni(generator, uni_dist) { if (!seed) seed = get_next_seed(); uni.engine().seed(seed); } #else mutable unsigned short state48[3]; random_uniform_slow(unsigned seed = 0) { if (!seed) seed = get_next_seed(); state48[0] = seed & 0xffff; state48[1] = seed >> 16; state48[2] = 42; erand48(state48); } #endif //! \brief Returns a random number from [0.0, 1.0) inline value_type operator () () const { #ifdef STXXL_BOOST_RANDOM return uni(); #else return erand48(state48); #endif } }; //! \brief Uniform [0, N) pseudo-random generator template struct random_number { typedef unsigned value_type; UniformRGen_ uniform; random_number(unsigned seed = 0) : uniform(seed) { } //! \brief Returns a random number from [0, N) inline value_type operator () (value_type N) const { return static_cast(uniform() * double(N)); } }; //! \brief Slow and precise uniform [0, 2^64) pseudo-random generator struct random_number64 { typedef stxxl::uint64 value_type; random_uniform_slow uniform; random_number64(unsigned seed = 0) : uniform(seed) { } //! \brief Returns a random number from [0, 2^64) inline value_type operator () () const { return static_cast(uniform() * (18446744073709551616.)); } }; __STXXL_END_NAMESPACE #endif // !STXXL_RAND_HEADER stxxl-1.3.1/include/stxxl/bits/singleton.h0000644000175000017500000000430211514123733020432 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/singleton.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2008, 2011 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_SINGLETON_HEADER #define STXXL_SINGLETON_HEADER #include #include #include #include #include __STXXL_BEGIN_NAMESPACE template class singleton : private noncopyable { typedef INSTANCE instance_type; typedef instance_type * instance_pointer; typedef volatile instance_pointer volatile_instance_pointer; static volatile_instance_pointer instance; static instance_pointer create_instance(); static void destroy_instance(); public: inline static instance_pointer get_instance() { if (!instance) return create_instance(); return instance; } }; template typename singleton::instance_pointer singleton::create_instance() { static mutex create_mutex; scoped_mutex_lock instance_write_lock(create_mutex); if (!instance) { instance = new instance_type(); if (destroy_on_exit) register_exit_handler(destroy_instance); } return instance; } template void singleton::destroy_instance() { instance_pointer inst = instance; //instance = NULL; instance = reinterpret_cast(unsigned_type(-1)); // bomb if used again delete inst; } template typename singleton::volatile_instance_pointer singleton::instance = NULL; __STXXL_END_NAMESPACE #endif // !STXXL_SINGLETON_HEADER stxxl-1.3.1/include/stxxl/bits/unused.h0000644000175000017500000000143711535151017017740 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/unused.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2007 Andreas Beckmann * Copyright (C) 2009 Johannes Singler * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_UNUSED_HEADER #define STXXL_UNUSED_HEADER #include __STXXL_BEGIN_NAMESPACE template inline void STXXL_UNUSED(const U &) { } __STXXL_END_NAMESPACE #endif // !STXXL_UNUSED_HEADER // vim: et:ts=4:sw=4 stxxl-1.3.1/include/stxxl/bits/verbose.h0000644000175000017500000001014211462510074020074 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/verbose.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2005-2006 Roman Dementiev * Copyright (C) 2007-2010 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_VERBOSE_HEADER #define STXXL_VERBOSE_HEADER #include #include #include #include #define _STXXL_PRNT_COUT (1 << 0) #define _STXXL_PRNT_CERR (1 << 1) #define _STXXL_PRNT_LOG (1 << 2) #define _STXXL_PRNT_ERRLOG (1 << 3) #define _STXXL_PRNT_ADDNEWLINE (1 << 16) #define _STXXL_PRNT_TIMESTAMP (1 << 17) #define _STXXL_PRNT_THREAD_ID (1 << 18) #define _STXXL_PRINT_FLAGS_DEFAULT (_STXXL_PRNT_COUT | _STXXL_PRNT_LOG) #define _STXXL_PRINT_FLAGS_ERROR (_STXXL_PRNT_CERR | _STXXL_PRNT_ERRLOG) #define _STXXL_PRINT_FLAGS_VERBOSE (_STXXL_PRINT_FLAGS_DEFAULT | _STXXL_PRNT_TIMESTAMP | _STXXL_PRNT_THREAD_ID) __STXXL_BEGIN_NAMESPACE void print_msg(const char * label, const std::string & msg, unsigned flags); __STXXL_END_NAMESPACE #define _STXXL_PRINT(label, message, flags) \ do { \ std::ostringstream str_; \ str_ << message; \ stxxl::print_msg(label, str_.str(), flags | _STXXL_PRNT_ADDNEWLINE); \ } while (false) #define _STXXL_NOT_VERBOSE do { } while (false) #ifdef STXXL_FORCE_VERBOSE_LEVEL #undef STXXL_VERBOSE_LEVEL #define STXXL_VERBOSE_LEVEL STXXL_FORCE_VERBOSE_LEVEL #endif #ifdef STXXL_DEFAULT_VERBOSE_LEVEL #ifndef STXXL_VERBOSE_LEVEL #define STXXL_VERBOSE_LEVEL STXXL_DEFAULT_VERBOSE_LEVEL #endif #endif #ifndef STXXL_VERBOSE_LEVEL #define STXXL_VERBOSE_LEVEL -1 #endif #if STXXL_VERBOSE_LEVEL > -10 #define STXXL_MSG(x) _STXXL_PRINT("STXXL-MSG", x, _STXXL_PRINT_FLAGS_DEFAULT) #else // Please do not report STXXL problems with STXXL_MSG disabled! #define STXXL_MSG(x) _STXXL_NOT_VERBOSE #endif #if STXXL_VERBOSE_LEVEL > -100 #define STXXL_ERRMSG(x) _STXXL_PRINT("STXXL-ERRMSG", x, _STXXL_PRINT_FLAGS_ERROR) #else // Please do not report STXXL problems with STXXL_ERRMSG disabled! #define STXXL_ERRMSG(x) _STXXL_NOT_VERBOSE #endif // STXXL_VERBOSE0 should be used for current debugging activity only, // and afterwards be replaced by STXXL_VERBOSE1 or higher. // Code that actively uses STXXL_VERBOSE0 should never get into a release. #if STXXL_VERBOSE_LEVEL > -1 #define STXXL_VERBOSE0(x) _STXXL_PRINT("STXXL-VERBOSE0", x, _STXXL_PRINT_FLAGS_VERBOSE) #else #define STXXL_VERBOSE0(x) _STXXL_NOT_VERBOSE #endif #if STXXL_VERBOSE_LEVEL > 0 #define STXXL_VERBOSE1(x) _STXXL_PRINT("STXXL-VERBOSE1", x, _STXXL_PRINT_FLAGS_VERBOSE) #else #define STXXL_VERBOSE1(x) _STXXL_NOT_VERBOSE #endif #define STXXL_VERBOSE(x) STXXL_VERBOSE1(x) #if STXXL_VERBOSE_LEVEL > 1 #define STXXL_VERBOSE2(x) _STXXL_PRINT("STXXL-VERBOSE2", x, _STXXL_PRINT_FLAGS_VERBOSE) #else #define STXXL_VERBOSE2(x) _STXXL_NOT_VERBOSE #endif #if STXXL_VERBOSE_LEVEL > 2 #define STXXL_VERBOSE3(x) _STXXL_PRINT("STXXL-VERBOSE3", x, _STXXL_PRINT_FLAGS_VERBOSE) #else #define STXXL_VERBOSE3(x) _STXXL_NOT_VERBOSE #endif //////////////////////////////////////////////////////////////////////////// #ifdef BOOST_MSVC #define stxxl_win_lasterror_exit(errmsg, exception_type) \ do { \ LPVOID lpMsgBuf; \ DWORD dw = GetLastError(); \ FormatMessage( \ FORMAT_MESSAGE_ALLOCATE_BUFFER | \ FORMAT_MESSAGE_FROM_SYSTEM, \ NULL, \ dw, \ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), \ (LPTSTR)&lpMsgBuf, \ 0, NULL); \ std::ostringstream str_; \ str_ << "Error in " << errmsg << ", error code " << dw << ": " << ((char *)lpMsgBuf); \ LocalFree(lpMsgBuf); \ throw exception_type(str_.str()); \ } while (false) #endif #endif // !STXXL_VERBOSE_HEADER // vim: et:ts=4:sw=4 stxxl-1.3.1/include/stxxl/bits/stream/0000755000175000017500000000000011536252421017554 5ustar andreasandreasstxxl-1.3.1/include/stxxl/bits/stream/stream.h0000644000175000017500000013562311535151017021230 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/stream/stream.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2003-2005 Roman Dementiev * Copyright (C) 2009, 2010 Andreas Beckmann * Copyright (C) 2010 Johannes Singler * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_STREAM_HEADER #define STXXL_STREAM_HEADER #include #include #include #include #include #include #ifndef STXXL_VERBOSE_MATERIALIZE #define STXXL_VERBOSE_MATERIALIZE STXXL_VERBOSE3 #endif __STXXL_BEGIN_NAMESPACE //! \brief Stream package subnamespace namespace stream { //! \weakgroup streampack Stream package //! Package that enables pipelining of consequent sorts //! and scans of the external data avoiding the saving the intermediate //! results on the disk, e.g. the output of a sort can be directly //! fed into a scan procedure without the need to save it on a disk. //! All components of the package are contained in the \c stxxl::stream //! namespace. //! //! STREAM ALGORITHM CONCEPT (Do not confuse with C++ input/output streams) //! //! \verbatim //! //! struct stream_algorithm // stream, pipe, whatever //! { //! typedef some_type value_type; //! //! const value_type & operator * () const; // return current element of the stream //! stream_algorithm & operator ++ (); // go to next element. precondition: empty() == false //! bool empty() const; // return true if end of stream is reached //! //! }; //! \endverbatim //! //! \{ //////////////////////////////////////////////////////////////////////// // STREAMIFY // //////////////////////////////////////////////////////////////////////// //! \brief A model of stream that retrieves the data from an input iterator //! For convenience use \c streamify function instead of direct instantiation //! of \c iterator2stream . template class iterator2stream { InputIterator_ current_, end_; public: //! \brief Standard stream typedef typedef typename std::iterator_traits::value_type value_type; iterator2stream(InputIterator_ begin, InputIterator_ end) : current_(begin), end_(end) { } iterator2stream(const iterator2stream & a) : current_(a.current_), end_(a.end_) { } //! \brief Standard stream method const value_type & operator * () const { return *current_; } const value_type * operator -> () const { return &(*current_); } //! \brief Standard stream method iterator2stream & operator ++ () { assert(end_ != current_); ++current_; return *this; } //! \brief Standard stream method bool empty() const { return (current_ == end_); } }; //! \brief Input iterator range to stream converter //! \param begin iterator, pointing to the first value //! \param end iterator, pointing to the last + 1 position, i.e. beyond the range //! \return an instance of a stream object template iterator2stream streamify(InputIterator_ begin, InputIterator_ end) { return iterator2stream(begin, end); } //! \brief Traits class of \c streamify function template struct streamify_traits { //! \brief return type (stream type) of \c streamify for \c InputIterator_ typedef iterator2stream stream_type; }; //! \brief A model of stream that retrieves data from an external \c stxxl::vector iterator. //! It is more efficient than generic \c iterator2stream thanks to use of overlapping //! For convenience use \c streamify function instead of direct instantiation //! of \c vector_iterator2stream . template class vector_iterator2stream { InputIterator_ current_, end_; typedef buf_istream buf_istream_type; typedef typename stxxl::compat_unique_ptr::result buf_istream_unique_ptr_type; mutable buf_istream_unique_ptr_type in; void delete_stream() { in.reset(); // delete object } public: typedef vector_iterator2stream Self_; //! \brief Standard stream typedef typedef typename std::iterator_traits::value_type value_type; vector_iterator2stream(InputIterator_ begin, InputIterator_ end, unsigned_type nbuffers = 0) : current_(begin), end_(end), in(static_cast(NULL)) { begin.flush(); // flush container typename InputIterator_::bids_container_iterator end_iter = end.bid() + ((end.block_offset()) ? 1 : 0); if (end_iter - begin.bid() > 0) { in.reset(new buf_istream_type(begin.bid(), end_iter, nbuffers ? nbuffers : (2 * config::get_instance()->disks_number()))); InputIterator_ cur = begin - begin.block_offset(); // skip the beginning of the block for ( ; cur != begin; ++cur) ++(*in); } } vector_iterator2stream(const Self_ & a) : current_(a.current_), end_(a.end_), in(a.in.release()) { } //! \brief Standard stream method const value_type & operator * () const { return **in; } const value_type * operator -> () const { return &(**in); } //! \brief Standard stream method Self_ & operator ++ () { assert(end_ != current_); ++current_; ++(*in); if (empty()) delete_stream(); return *this; } //! \brief Standard stream method bool empty() const { return (current_ == end_); } virtual ~vector_iterator2stream() { delete_stream(); // not needed actually } }; //! \brief Input external \c stxxl::vector iterator range to stream converter //! It is more efficient than generic input iterator \c streamify thanks to use of overlapping //! \param begin iterator, pointing to the first value //! \param end iterator, pointing to the last + 1 position, i.e. beyond the range //! \param nbuffers number of blocks used for overlapped reading (0 is default, //! which equals to (2 * number_of_disks) //! \return an instance of a stream object template vector_iterator2stream > streamify( stxxl::vector_iterator begin, stxxl::vector_iterator end, unsigned_type nbuffers = 0) { STXXL_VERBOSE1("streamify for vector_iterator range is called"); return vector_iterator2stream > (begin, end, nbuffers); } template struct streamify_traits > { typedef vector_iterator2stream > stream_type; }; //! \brief Input external \c stxxl::vector const iterator range to stream converter //! It is more efficient than generic input iterator \c streamify thanks to use of overlapping //! \param begin const iterator, pointing to the first value //! \param end const iterator, pointing to the last + 1 position, i.e. beyond the range //! \param nbuffers number of blocks used for overlapped reading (0 is default, //! which equals to (2 * number_of_disks) //! \return an instance of a stream object template vector_iterator2stream > streamify( stxxl::const_vector_iterator begin, stxxl::const_vector_iterator end, unsigned_type nbuffers = 0) { STXXL_VERBOSE1("streamify for const_vector_iterator range is called"); return vector_iterator2stream > (begin, end, nbuffers); } template struct streamify_traits > { typedef vector_iterator2stream > stream_type; }; //! \brief Version of \c iterator2stream. Switches between \c vector_iterator2stream and \c iterator2stream . //! //! small range switches between //! \c vector_iterator2stream and \c iterator2stream . //! iterator2stream is chosen if the input iterator range //! is small ( < B ) template class vector_iterator2stream_sr { vector_iterator2stream * vec_it_stream; iterator2stream * it_stream; typedef typename InputIterator_::block_type block_type; public: typedef vector_iterator2stream_sr Self_; //! \brief Standard stream typedef typedef typename std::iterator_traits::value_type value_type; vector_iterator2stream_sr(InputIterator_ begin, InputIterator_ end, unsigned_type nbuffers = 0) { if (end - begin < block_type::size) { STXXL_VERBOSE1("vector_iterator2stream_sr::vector_iterator2stream_sr: Choosing iterator2stream"); it_stream = new iterator2stream(begin, end); vec_it_stream = NULL; } else { STXXL_VERBOSE1("vector_iterator2stream_sr::vector_iterator2stream_sr: Choosing vector_iterator2stream"); it_stream = NULL; vec_it_stream = new vector_iterator2stream(begin, end, nbuffers); } } vector_iterator2stream_sr(const Self_ & a) : vec_it_stream(a.vec_it_stream), it_stream(a.it_stream) { } //! \brief Standard stream method const value_type & operator * () const { if (it_stream) return **it_stream; return **vec_it_stream; } const value_type * operator -> () const { if (it_stream) return &(**it_stream); return &(**vec_it_stream); } //! \brief Standard stream method Self_ & operator ++ () { if (it_stream) ++(*it_stream); else ++(*vec_it_stream); return *this; } //! \brief Standard stream method bool empty() const { if (it_stream) return it_stream->empty(); return vec_it_stream->empty(); } virtual ~vector_iterator2stream_sr() { if (it_stream) delete it_stream; else delete vec_it_stream; } }; //! \brief Version of \c streamify. Switches from \c vector_iterator2stream to \c iterator2stream for small ranges. template vector_iterator2stream_sr > streamify_sr( stxxl::vector_iterator begin, stxxl::vector_iterator end, unsigned_type nbuffers = 0) { STXXL_VERBOSE1("streamify_sr for vector_iterator range is called"); return vector_iterator2stream_sr > (begin, end, nbuffers); } //! \brief Version of \c streamify. Switches from \c vector_iterator2stream to \c iterator2stream for small ranges. template vector_iterator2stream_sr > streamify_sr( stxxl::const_vector_iterator begin, stxxl::const_vector_iterator end, unsigned_type nbuffers = 0) { STXXL_VERBOSE1("streamify_sr for const_vector_iterator range is called"); return vector_iterator2stream_sr > (begin, end, nbuffers); } //////////////////////////////////////////////////////////////////////// // MATERIALIZE // //////////////////////////////////////////////////////////////////////// //! \brief Stores consecutively stream content to an output iterator //! \param in stream to be stored used as source //! \param out output iterator used as destination //! \return value of the output iterator after all increments, //! i.e. points to the first unwritten value //! \pre Output (range) is large enough to hold the all elements in the input stream template OutputIterator_ materialize(StreamAlgorithm_ & in, OutputIterator_ out) { STXXL_VERBOSE_MATERIALIZE(STXXL_PRETTY_FUNCTION_NAME); while (!in.empty()) { *out = *in; ++out; ++in; } return out; } //! \brief Stores consecutively stream content to an output iterator range \b until end of the stream or end of the iterator range is reached //! \param in stream to be stored used as source //! \param outbegin output iterator used as destination //! \param outend output end iterator, pointing beyond the output range //! \return value of the output iterator after all increments, //! i.e. points to the first unwritten value //! \pre Output range is large enough to hold the all elements in the input stream //! //! This function is useful when you do not know the length of the stream beforehand. template OutputIterator_ materialize(StreamAlgorithm_ & in, OutputIterator_ outbegin, OutputIterator_ outend) { STXXL_VERBOSE_MATERIALIZE(STXXL_PRETTY_FUNCTION_NAME); while ((!in.empty()) && outend != outbegin) { *outbegin = *in; ++outbegin; ++in; } return outbegin; } //! \brief Stores consecutively stream content to an output \c stxxl::vector iterator \b until end of the stream or end of the iterator range is reached //! \param in stream to be stored used as source //! \param outbegin output \c stxxl::vector iterator used as destination //! \param outend output end iterator, pointing beyond the output range //! \param nbuffers number of blocks used for overlapped writing (0 is default, //! which equals to (2 * number_of_disks) //! \return value of the output iterator after all increments, //! i.e. points to the first unwritten value //! \pre Output range is large enough to hold the all elements in the input stream //! //! This function is useful when you do not know the length of the stream beforehand. template stxxl::vector_iterator materialize(StreamAlgorithm_ & in, stxxl::vector_iterator outbegin, stxxl::vector_iterator outend, unsigned_type nbuffers = 0) { STXXL_VERBOSE_MATERIALIZE(STXXL_PRETTY_FUNCTION_NAME); typedef stxxl::vector_iterator ExtIterator; typedef stxxl::const_vector_iterator ConstExtIterator; typedef buf_ostream buf_ostream_type; while (outbegin.block_offset()) // go to the beginning of the block // of the external vector { if (in.empty() || outbegin == outend) return outbegin; *outbegin = *in; ++outbegin; ++in; } if (nbuffers == 0) nbuffers = 2 * config::get_instance()->disks_number(); outbegin.flush(); // flush container // create buffered write stream for blocks buf_ostream_type outstream(outbegin.bid(), nbuffers); assert(outbegin.block_offset() == 0); // delay calling block_externally_updated() until the block is // completely filled (and written out) in outstream ConstExtIterator prev_block = outbegin; while (!in.empty() && outend != outbegin) { if (outbegin.block_offset() == 0) { if (prev_block != outbegin) { prev_block.block_externally_updated(); prev_block = outbegin; } } *outstream = *in; ++outbegin; ++outstream; ++in; } ConstExtIterator const_out = outbegin; while (const_out.block_offset()) // filling the rest of the block { *outstream = *const_out; ++const_out; ++outstream; } if (prev_block != outbegin) prev_block.block_externally_updated(); outbegin.flush(); return outbegin; } //! \brief Stores consecutively stream content to an output \c stxxl::vector iterator //! \param in stream to be stored used as source //! \param out output \c stxxl::vector iterator used as destination //! \param nbuffers number of blocks used for overlapped writing (0 is default, //! which equals to (2 * number_of_disks) //! \return value of the output iterator after all increments, //! i.e. points to the first unwritten value //! \pre Output (range) is large enough to hold the all elements in the input stream template stxxl::vector_iterator materialize(StreamAlgorithm_ & in, stxxl::vector_iterator out, unsigned_type nbuffers = 0) { STXXL_VERBOSE_MATERIALIZE(STXXL_PRETTY_FUNCTION_NAME); typedef stxxl::vector_iterator ExtIterator; typedef stxxl::const_vector_iterator ConstExtIterator; typedef buf_ostream buf_ostream_type; // on the I/O complexity of "materialize": // crossing block boundary causes O(1) I/Os // if you stay in a block, then materialize function accesses only the cache of the // vector (only one block indeed), amortized complexity should apply here while (out.block_offset()) // go to the beginning of the block // of the external vector { if (in.empty()) return out; *out = *in; ++out; ++in; } if (nbuffers == 0) nbuffers = 2 * config::get_instance()->disks_number(); out.flush(); // flush container // create buffered write stream for blocks buf_ostream_type outstream(out.bid(), nbuffers); assert(out.block_offset() == 0); // delay calling block_externally_updated() until the block is // completely filled (and written out) in outstream ConstExtIterator prev_block = out; while (!in.empty()) { if (out.block_offset() == 0) { if (prev_block != out) { prev_block.block_externally_updated(); prev_block = out; } } // tells the vector that the block was modified *outstream = *in; ++out; ++outstream; ++in; } ConstExtIterator const_out = out; while (const_out.block_offset()) { *outstream = *const_out; // might cause I/Os for loading the page that ++const_out; // contains data beyond out ++outstream; } if (prev_block != out) prev_block.block_externally_updated(); out.flush(); return out; } //! \brief Reads stream content and discards it. //! Useful where you do not need the processed stream anymore, //! but are just interested in side effects, or just for debugging. //! \param in input stream template void discard(StreamAlgorithm_ & in) { while (!in.empty()) { *in; ++in; } } //////////////////////////////////////////////////////////////////////// // GENERATE // //////////////////////////////////////////////////////////////////////// //! \brief A model of stream that outputs data from an adaptable generator functor //! For convenience use \c streamify function instead of direct instantiation //! of \c generator2stream . template class generator2stream { public: //! \brief Standard stream typedef typedef T value_type; private: Generator_ gen_; value_type current_; public: generator2stream(Generator_ g) : gen_(g), current_(gen_()) { } generator2stream(const generator2stream & a) : gen_(a.gen_), current_(a.current_) { } //! \brief Standard stream method const value_type & operator * () const { return current_; } const value_type * operator -> () const { return ¤t_; } //! \brief Standard stream method generator2stream & operator ++ () { current_ = gen_(); return *this; } //! \brief Standard stream method bool empty() const { return false; } }; //! \brief Adaptable generator to stream converter //! \param gen_ generator object //! \return an instance of a stream object template generator2stream streamify(Generator_ gen_) { return generator2stream(gen_); } //////////////////////////////////////////////////////////////////////// // TRANSFORM // //////////////////////////////////////////////////////////////////////// struct Stopper { }; //! \brief Processes (up to) 6 input streams using given operation functor //! //! \tparam Operation_ type of the operation (type of an //! adaptable functor that takes 6 parameters) //! \tparam Input1_ type of the 1st input //! \tparam Input2_ type of the 2nd input //! \tparam Input3_ type of the 3rd input //! \tparam Input4_ type of the 4th input //! \tparam Input5_ type of the 5th input //! \tparam Input6_ type of the 6th input template class transform { Operation_ & op; Input1_ & i1; Input2_ & i2; Input3_ & i3; Input4_ & i4; Input5_ & i5; Input6_ & i6; public: //! \brief Standard stream typedef typedef typename Operation_::value_type value_type; private: value_type current; public: //! \brief Construction transform(Operation_ & o, Input1_ & i1_, Input2_ & i2_, Input3_ & i3_, Input4_ & i4_, Input5_ & i5_, Input5_ & i6_) : op(o), i1(i1_), i2(i2_), i3(i3_), i4(i4_), i5(i5_), i6(i6_) { if (!empty()) current = op(*i1, *i2, *i3, *i4, *i5, *i6); } //! \brief Standard stream method const value_type & operator * () const { return current; } const value_type * operator -> () const { return ¤t; } //! \brief Standard stream method transform & operator ++ () { ++i1; ++i2; ++i3; ++i4; ++i5; ++i6; if (!empty()) current = op(*i1, *i2, *i3, *i4, *i5, *i6); return *this; } //! \brief Standard stream method bool empty() const { return i1.empty() || i2.empty() || i3.empty() || i4.empty() || i5.empty() || i6.empty(); } }; // Specializations //////////////////////////////////////////////////////////////////////// // TRANSFORM (1 input stream) // //////////////////////////////////////////////////////////////////////// //! \brief Processes an input stream using given operation functor //! //! \tparam Operation_ type of the operation (type of an //! adaptable functor that takes 1 parameter) //! \tparam Input1_ type of the input //! \remark This is a specialization of \c transform . template class transform { Operation_ & op; Input1_ & i1; public: //! \brief Standard stream typedef typedef typename Operation_::value_type value_type; private: value_type current; public: //! \brief Construction transform(Operation_ & o, Input1_ & i1_) : op(o), i1(i1_) { if (!empty()) current = op(*i1); } //! \brief Standard stream method const value_type & operator * () const { return current; } const value_type * operator -> () const { return ¤t; } //! \brief Standard stream method transform & operator ++ () { ++i1; if (!empty()) current = op(*i1); return *this; } //! \brief Standard stream method bool empty() const { return i1.empty(); } }; //////////////////////////////////////////////////////////////////////// // TRANSFORM (2 input streams) // //////////////////////////////////////////////////////////////////////// //! \brief Processes 2 input streams using given operation functor //! //! \tparam Operation_ type of the operation (type of an //! adaptable functor that takes 2 parameters) //! \tparam Input1_ type of the 1st input //! \tparam Input2_ type of the 2nd input //! \remark This is a specialization of \c transform . template class transform { Operation_ & op; Input1_ & i1; Input2_ & i2; public: //! \brief Standard stream typedef typedef typename Operation_::value_type value_type; private: value_type current; public: //! \brief Construction transform(Operation_ & o, Input1_ & i1_, Input2_ & i2_) : op(o), i1(i1_), i2(i2_) { if (!empty()) current = op(*i1, *i2); } //! \brief Standard stream method const value_type & operator * () const { return current; } const value_type * operator -> () const { return ¤t; } //! \brief Standard stream method transform & operator ++ () { ++i1; ++i2; if (!empty()) current = op(*i1, *i2); return *this; } //! \brief Standard stream method bool empty() const { return i1.empty() || i2.empty(); } }; //////////////////////////////////////////////////////////////////////// // TRANSFORM (3 input streams) // //////////////////////////////////////////////////////////////////////// //! \brief Processes 3 input streams using given operation functor //! //! \tparam Operation_ type of the operation (type of an //! adaptable functor that takes 3 parameters) //! \tparam Input1_ type of the 1st input //! \tparam Input2_ type of the 2nd input //! \tparam Input3_ type of the 3rd input //! \remark This is a specialization of \c transform . template class transform { Operation_ & op; Input1_ & i1; Input2_ & i2; Input3_ & i3; public: //! \brief Standard stream typedef typedef typename Operation_::value_type value_type; private: value_type current; public: //! \brief Construction transform(Operation_ & o, Input1_ & i1_, Input2_ & i2_, Input3_ & i3_) : op(o), i1(i1_), i2(i2_), i3(i3_) { if (!empty()) current = op(*i1, *i2, *i3); } //! \brief Standard stream method const value_type & operator * () const { return current; } const value_type * operator -> () const { return ¤t; } //! \brief Standard stream method transform & operator ++ () { ++i1; ++i2; ++i3; if (!empty()) current = op(*i1, *i2, *i3); return *this; } //! \brief Standard stream method bool empty() const { return i1.empty() || i2.empty() || i3.empty(); } }; //////////////////////////////////////////////////////////////////////// // TRANSFORM (4 input streams) // //////////////////////////////////////////////////////////////////////// //! \brief Processes 4 input streams using given operation functor //! //! \tparam Operation_ type of the operation (type of an //! adaptable functor that takes 4 parameters) //! \tparam Input1_ type of the 1st input //! \tparam Input2_ type of the 2nd input //! \tparam Input3_ type of the 3rd input //! \tparam Input4_ type of the 4th input //! \remark This is a specialization of \c transform . template class transform { Operation_ & op; Input1_ & i1; Input2_ & i2; Input3_ & i3; Input4_ & i4; public: //! \brief Standard stream typedef typedef typename Operation_::value_type value_type; private: value_type current; public: //! \brief Construction transform(Operation_ & o, Input1_ & i1_, Input2_ & i2_, Input3_ & i3_, Input4_ & i4_) : op(o), i1(i1_), i2(i2_), i3(i3_), i4(i4_) { if (!empty()) current = op(*i1, *i2, *i3, *i4); } //! \brief Standard stream method const value_type & operator * () const { return current; } const value_type * operator -> () const { return ¤t; } //! \brief Standard stream method transform & operator ++ () { ++i1; ++i2; ++i3; ++i4; if (!empty()) current = op(*i1, *i2, *i3, *i4); return *this; } //! \brief Standard stream method bool empty() const { return i1.empty() || i2.empty() || i3.empty() || i4.empty(); } }; //////////////////////////////////////////////////////////////////////// // TRANSFORM (5 input streams) // //////////////////////////////////////////////////////////////////////// //! \brief Processes 5 input streams using given operation functor //! //! \tparam Operation_ type of the operation (type of an //! adaptable functor that takes 5 parameters) //! \tparam Input1_ type of the 1st input //! \tparam Input2_ type of the 2nd input //! \tparam Input3_ type of the 3rd input //! \tparam Input4_ type of the 4th input //! \tparam Input5_ type of the 5th input //! \remark This is a specialization of \c transform . template class transform { Operation_ & op; Input1_ & i1; Input2_ & i2; Input3_ & i3; Input4_ & i4; Input5_ & i5; public: //! \brief Standard stream typedef typedef typename Operation_::value_type value_type; private: value_type current; public: //! \brief Construction transform(Operation_ & o, Input1_ & i1_, Input2_ & i2_, Input3_ & i3_, Input4_ & i4_, Input5_ & i5_) : op(o), i1(i1_), i2(i2_), i3(i3_), i4(i4_), i5(i5_) { if (!empty()) current = op(*i1, *i2, *i3, *i4, *i5); } //! \brief Standard stream method const value_type & operator * () const { return current; } const value_type * operator -> () const { return ¤t; } //! \brief Standard stream method transform & operator ++ () { ++i1; ++i2; ++i3; ++i4; ++i5; if (!empty()) current = op(*i1, *i2, *i3, *i4, *i5); return *this; } //! \brief Standard stream method bool empty() const { return i1.empty() || i2.empty() || i3.empty() || i4.empty() || i5.empty(); } }; //////////////////////////////////////////////////////////////////////// // MAKE TUPLE // //////////////////////////////////////////////////////////////////////// //! \brief Creates stream of 6-tuples from 6 input streams //! //! \tparam Input1_ type of the 1st input //! \tparam Input2_ type of the 2nd input //! \tparam Input3_ type of the 3rd input //! \tparam Input4_ type of the 4th input //! \tparam Input5_ type of the 5th input //! \tparam Input6_ type of the 6th input template class make_tuple { Input1_ & i1; Input2_ & i2; Input3_ & i3; Input4_ & i4; Input5_ & i5; Input6_ & i6; public: //! \brief Standard stream typedef typedef typename stxxl::tuple< typename Input1_::value_type, typename Input2_::value_type, typename Input3_::value_type, typename Input4_::value_type, typename Input5_::value_type, typename Input6_::value_type > value_type; private: value_type current; public: //! \brief Construction make_tuple( Input1_ & i1_, Input2_ & i2_, Input3_ & i3_, Input4_ & i4_, Input5_ & i5_, Input6_ & i6_ ) : i1(i1_), i2(i2_), i3(i3_), i4(i4_), i5(i5_), i6(i6_), current(value_type(*i1, *i2, *i3, *i4, *i5, *i6)) { } //! \brief Standard stream method const value_type & operator * () const { return current; } const value_type * operator -> () const { return ¤t; } //! \brief Standard stream method make_tuple & operator ++ () { ++i1; ++i2; ++i3; ++i4; ++i5; ++i6; if (!empty()) current = value_type(*i1, *i2, *i3, *i4, *i5, *i6); return *this; } //! \brief Standard stream method bool empty() const { return i1.empty() || i2.empty() || i3.empty() || i4.empty() || i5.empty() || i6.empty(); } }; //! \brief Creates stream of 2-tuples (pairs) from 2 input streams //! //! \tparam Input1_ type of the 1st input //! \tparam Input2_ type of the 2nd input //! \remark A specialization of \c make_tuple . template class make_tuple { Input1_ & i1; Input2_ & i2; public: //! \brief Standard stream typedef typedef typename stxxl::tuple< typename Input1_::value_type, typename Input2_::value_type > value_type; private: value_type current; public: //! \brief Construction make_tuple( Input1_ & i1_, Input2_ & i2_ ) : i1(i1_), i2(i2_) { if (!empty()) { current = value_type(*i1, *i2); } } //! \brief Standard stream method const value_type & operator * () const { return current; } const value_type * operator -> () const { return ¤t; } //! \brief Standard stream method make_tuple & operator ++ () { ++i1; ++i2; if (!empty()) current = value_type(*i1, *i2); return *this; } //! \brief Standard stream method bool empty() const { return i1.empty() || i2.empty(); } }; //! \brief Creates stream of 3-tuples from 3 input streams //! //! \tparam Input1_ type of the 1st input //! \tparam Input2_ type of the 2nd input //! \tparam Input3_ type of the 3rd input //! \remark A specialization of \c make_tuple . template class make_tuple { Input1_ & i1; Input2_ & i2; Input3_ & i3; public: //! \brief Standard stream typedef typedef typename stxxl::tuple< typename Input1_::value_type, typename Input2_::value_type, typename Input3_::value_type > value_type; private: value_type current; public: //! \brief Construction make_tuple( Input1_ & i1_, Input2_ & i2_, Input3_ & i3_ ) : i1(i1_), i2(i2_), i3(i3_), current(value_type(*i1, *i2, *i3)) { } //! \brief Standard stream method const value_type & operator * () const { return current; } const value_type * operator -> () const { return ¤t; } //! \brief Standard stream method make_tuple & operator ++ () { ++i1; ++i2; ++i3; if (!empty()) current = value_type(*i1, *i2, *i3); return *this; } //! \brief Standard stream method bool empty() const { return i1.empty() || i2.empty() || i3.empty(); } }; //! \brief Creates stream of 4-tuples from 4 input streams //! //! \tparam Input1_ type of the 1st input //! \tparam Input2_ type of the 2nd input //! \tparam Input3_ type of the 3rd input //! \tparam Input4_ type of the 4th input //! \remark A specialization of \c make_tuple . template class make_tuple { Input1_ & i1; Input2_ & i2; Input3_ & i3; Input4_ & i4; public: //! \brief Standard stream typedef typedef typename stxxl::tuple< typename Input1_::value_type, typename Input2_::value_type, typename Input3_::value_type, typename Input4_::value_type > value_type; private: value_type current; public: //! \brief Construction make_tuple( Input1_ & i1_, Input2_ & i2_, Input3_ & i3_, Input4_ & i4_ ) : i1(i1_), i2(i2_), i3(i3_), i4(i4_), current(value_type(*i1, *i2, *i3, *i4)) { } //! \brief Standard stream method const value_type & operator * () const { return current; } const value_type * operator -> () const { return ¤t; } //! \brief Standard stream method make_tuple & operator ++ () { ++i1; ++i2; ++i3; ++i4; if (!empty()) current = value_type(*i1, *i2, *i3, *i4); return *this; } //! \brief Standard stream method bool empty() const { return i1.empty() || i2.empty() || i3.empty() || i4.empty(); } }; //! \brief Creates stream of 5-tuples from 5 input streams //! //! \tparam Input1_ type of the 1st input //! \tparam Input2_ type of the 2nd input //! \tparam Input3_ type of the 3rd input //! \tparam Input4_ type of the 4th input //! \tparam Input5_ type of the 5th input //! \remark A specialization of \c make_tuple . template < class Input1_, class Input2_, class Input3_, class Input4_, class Input5_ > class make_tuple { Input1_ & i1; Input2_ & i2; Input3_ & i3; Input4_ & i4; Input5_ & i5; public: //! \brief Standard stream typedef typedef typename stxxl::tuple< typename Input1_::value_type, typename Input2_::value_type, typename Input3_::value_type, typename Input4_::value_type, typename Input5_::value_type > value_type; private: value_type current; public: //! \brief Construction make_tuple( Input1_ & i1_, Input2_ & i2_, Input3_ & i3_, Input4_ & i4_, Input5_ & i5_ ) : i1(i1_), i2(i2_), i3(i3_), i4(i4_), i5(i5_), current(value_type(*i1, *i2, *i3, *i4, *i5)) { } //! \brief Standard stream method const value_type & operator * () const { return current; } const value_type * operator -> () const { return ¤t; } //! \brief Standard stream method make_tuple & operator ++ () { ++i1; ++i2; ++i3; ++i4; ++i5; if (!empty()) current = value_type(*i1, *i2, *i3, *i4, *i5); return *this; } //! \brief Standard stream method bool empty() const { return i1.empty() || i2.empty() || i3.empty() || i4.empty() || i5.empty(); } }; //! \} } __STXXL_END_NAMESPACE #include #include #endif // !STXXL_STREAM_HEADER // vim: et:ts=4:sw=4 stxxl-1.3.1/include/stxxl/bits/stream/choose.h0000644000175000017500000001710611535151017021210 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/stream/choose.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2003-2005 Roman Dementiev * Copyright (C) 2010 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_STREAM__CHOOSE_H_ #define STXXL_STREAM__CHOOSE_H_ #include __STXXL_BEGIN_NAMESPACE //! \brief Stream package subnamespace namespace stream { //////////////////////////////////////////////////////////////////////// // CHOOSE // //////////////////////////////////////////////////////////////////////// template class choose { }; //! \brief Creates stream from a tuple stream taking the first component of each tuple //! //! \tparam Input_ type of the input tuple stream //! //! \remark Tuple stream is a stream which \c value_type is \c stxxl::tuple . template class choose { Input_ & in; typedef typename Input_::value_type tuple_type; public: //! \brief Standard stream typedef typedef typename tuple_type::first_type value_type; //! \brief Construction choose(Input_ & in_) : in(in_) { } //! \brief Standard stream method const value_type & operator * () const { return (*in).first; } const value_type * operator -> () const { return &(*in).first; } //! \brief Standard stream method choose & operator ++ () { ++in; return *this; } //! \brief Standard stream method bool empty() const { return in.empty(); } }; //! \brief Creates stream from a tuple stream taking the second component of each tuple //! //! \tparam Input_ type of the input tuple stream //! //! \remark Tuple stream is a stream which \c value_type is \c stxxl::tuple . template class choose { Input_ & in; typedef typename Input_::value_type tuple_type; public: //! \brief Standard stream typedef typedef typename tuple_type::second_type value_type; //! \brief Construction choose(Input_ & in_) : in(in_) { } //! \brief Standard stream method const value_type & operator * () const { return (*in).second; } const value_type * operator -> () const { return &(*in).second; } //! \brief Standard stream method choose & operator ++ () { ++in; return *this; } //! \brief Standard stream method bool empty() const { return in.empty(); } }; //! \brief Creates stream from a tuple stream taking the third component of each tuple //! //! \tparam Input_ type of the input tuple stream //! //! \remark Tuple stream is a stream which \c value_type is \c stxxl::tuple . template class choose { Input_ & in; typedef typename Input_::value_type tuple_type; public: //! \brief Standard stream typedef typedef typename tuple_type::third_type value_type; //! \brief Construction choose(Input_ & in_) : in(in_) { } //! \brief Standard stream method const value_type & operator * () const { return (*in).third; } const value_type * operator -> () const { return &(*in).third; } //! \brief Standard stream method choose & operator ++ () { ++in; return *this; } //! \brief Standard stream method bool empty() const { return in.empty(); } }; //! \brief Creates stream from a tuple stream taking the fourth component of each tuple //! //! \tparam Input_ type of the input tuple stream //! //! \remark Tuple stream is a stream which \c value_type is \c stxxl::tuple . template class choose { Input_ & in; typedef typename Input_::value_type tuple_type; public: //! \brief Standard stream typedef typedef typename tuple_type::fourth_type value_type; //! \brief Construction choose(Input_ & in_) : in(in_) { } //! \brief Standard stream method const value_type & operator * () const { return (*in).fourth; } const value_type * operator -> () const { return &(*in).fourth; } //! \brief Standard stream method choose & operator ++ () { ++in; return *this; } //! \brief Standard stream method bool empty() const { return in.empty(); } }; //! \brief Creates stream from a tuple stream taking the fifth component of each tuple //! //! \tparam Input_ type of the input tuple stream //! //! \remark Tuple stream is a stream which \c value_type is \c stxxl::tuple . template class choose { Input_ & in; typedef typename Input_::value_type tuple_type; public: //! \brief Standard stream typedef typedef typename tuple_type::fifth_type value_type; //! \brief Construction choose(Input_ & in_) : in(in_) { } //! \brief Standard stream method const value_type & operator * () const { return (*in).fifth; } const value_type * operator -> () const { return &(*in).fifth; } //! \brief Standard stream method choose & operator ++ () { ++in; return *this; } //! \brief Standard stream method bool empty() const { return in.empty(); } }; //! \brief Creates stream from a tuple stream taking the sixth component of each tuple //! //! \tparam Input_ type of the input tuple stream //! //! \remark Tuple stream is a stream which \c value_type is \c stxxl::tuple . template class choose { Input_ & in; typedef typename Input_::value_type tuple_type; public: //! \brief Standard stream typedef typedef typename tuple_type::sixth_type value_type; //! \brief Construction choose(Input_ & in_) : in(in_) { } //! \brief Standard stream method const value_type & operator * () const { return (*in).sixth; } const value_type * operator -> () const { return &(*in).sixth; } //! \brief Standard stream method choose & operator ++ () { ++in; return *this; } //! \brief Standard stream method bool empty() const { return in.empty(); } }; //! \} } __STXXL_END_NAMESPACE #include #endif // !STXXL_STREAM__CHOOSE_H_ // vim: et:ts=4:sw=4 stxxl-1.3.1/include/stxxl/bits/stream/sort_stream.h0000644000175000017500000015722411535540436022307 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/stream/sort_stream.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2002-2005 Roman Dementiev * Copyright (C) 2006-2008 Johannes Singler * Copyright (C) 2008-2010 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_SORT_STREAM_HEADER #define STXXL_SORT_STREAM_HEADER #ifdef STXXL_BOOST_CONFIG #include #endif #include #include #include #include #include #include #include #include __STXXL_BEGIN_NAMESPACE namespace stream { //! \addtogroup streampack Stream package //! \{ //////////////////////////////////////////////////////////////////////// // CREATE RUNS // //////////////////////////////////////////////////////////////////////// //! \brief Forms sorted runs of data from a stream //! //! \tparam Input_ type of the input stream //! \tparam Cmp_ type of comparison object used for sorting the runs //! \tparam BlockSize_ size of blocks used to store the runs (in bytes) //! \tparam AllocStr_ functor that defines allocation strategy for the runs template < class Input_, class Cmp_, unsigned BlockSize_ = STXXL_DEFAULT_BLOCK_SIZE(typename Input_::value_type), class AllocStr_ = STXXL_DEFAULT_ALLOC_STRATEGY> class basic_runs_creator : private noncopyable { protected: Input_ & input; Cmp_ cmp; public: typedef Cmp_ cmp_type; typedef typename Input_::value_type value_type; typedef typed_block block_type; typedef sort_helper::trigger_entry trigger_entry_type; typedef sorted_runs sorted_runs_type; private: typedef typename sorted_runs_type::run_type run_type; sorted_runs_type result_; // stores the result (sorted runs) unsigned_type m_; // memory for internal use in blocks bool result_computed; // true iff result is already computed (used in 'result' method) //! \brief Fetch data from input into blocks[first_idx,last_idx). unsigned_type fetch(block_type * blocks, unsigned_type first_idx, unsigned_type last_idx) { typename element_iterator_traits::element_iterator output = make_element_iterator(blocks, first_idx); unsigned_type curr_idx = first_idx; while (!input.empty() && curr_idx != last_idx) { *output = *input; ++input; ++output; ++curr_idx; } return curr_idx; } void fill_with_max_value(block_type * blocks, unsigned_type num_blocks, unsigned_type first_idx) { unsigned_type last_idx = num_blocks * block_type::size; if (first_idx < last_idx) { typename element_iterator_traits::element_iterator curr = make_element_iterator(blocks, first_idx); while (first_idx != last_idx) { *curr = cmp.max_value(); ++curr; ++first_idx; } } } //! \brief Sort a specific run, contained in a sequences of blocks. void sort_run(block_type * run, unsigned_type elements) { potentially_parallel:: sort(make_element_iterator(run, 0), make_element_iterator(run, elements), cmp); } void compute_result(); public: //! \brief Create the object //! \param i input stream //! \param c comparator object //! \param memory_to_use memory amount that is allowed to used by the sorter in bytes basic_runs_creator(Input_ & i, Cmp_ c, unsigned_type memory_to_use) : input(i), cmp(c), m_(memory_to_use / BlockSize_ / sort_memory_usage_factor()), result_computed(false) { sort_helper::verify_sentinel_strict_weak_ordering(cmp); if (!(2 * BlockSize_ * sort_memory_usage_factor() <= memory_to_use)) { throw bad_parameter("stxxl::runs_creator<>:runs_creator(): INSUFFICIENT MEMORY provided, please increase parameter 'memory_to_use'"); } assert(m_ > 0); } //! \brief Returns the sorted runs object //! \return Sorted runs object. The result is computed lazily, i.e. on the first call //! \remark Returned object is intended to be used by \c runs_merger object as input const sorted_runs_type & result() { if (!result_computed) { compute_result(); result_computed = true; #ifdef STXXL_PRINT_STAT_AFTER_RF STXXL_MSG(*stats::get_instance()); #endif //STXXL_PRINT_STAT_AFTER_RF } return result_; } }; //! \brief Finish the results, i. e. create all runs. //! //! This is the main routine of this class. template void basic_runs_creator::compute_result() { unsigned_type i = 0; unsigned_type m2 = m_ / 2; const unsigned_type el_in_run = m2 * block_type::size; // # el in a run STXXL_VERBOSE1("basic_runs_creator::compute_result m2=" << m2); unsigned_type blocks1_length = 0, blocks2_length = 0; block_type * Blocks1 = NULL; #ifndef STXXL_SMALL_INPUT_PSORT_OPT Blocks1 = new block_type[m2 * 2]; #else while (!input.empty() && blocks1_length != block_type::size) { result_.small_.push_back(*input); ++input; ++blocks1_length; } if (blocks1_length == block_type::size && !input.empty()) { Blocks1 = new block_type[m2 * 2]; std::copy(result_.small_.begin(), result_.small_.end(), Blocks1[0].begin()); result_.small_.clear(); } else { STXXL_VERBOSE1("basic_runs_creator: Small input optimization, input length: " << blocks1_length); result_.elements = blocks1_length; potentially_parallel:: sort(result_.small_.begin(), result_.small_.end(), cmp); return; } #endif //STXXL_SMALL_INPUT_PSORT_OPT // the first block may be there already blocks1_length = fetch(Blocks1, blocks1_length, el_in_run); // sort first run sort_run(Blocks1, blocks1_length); if (blocks1_length <= block_type::size && input.empty()) { // small input, do not flush it on the disk(s) STXXL_VERBOSE1("basic_runs_creator: Small input optimization, input length: " << blocks1_length); assert(result_.small_.empty()); result_.small_.insert(result_.small_.end(), Blocks1[0].begin(), Blocks1[0].begin() + blocks1_length); result_.elements = blocks1_length; delete[] Blocks1; return; } block_type * Blocks2 = Blocks1 + m2; block_manager * bm = block_manager::get_instance(); request_ptr * write_reqs = new request_ptr[m2]; run_type run; unsigned_type cur_run_size = div_ceil(blocks1_length, block_type::size); // in blocks run.resize(cur_run_size); bm->new_blocks(AllocStr_(), make_bid_iterator(run.begin()), make_bid_iterator(run.end())); disk_queues::get_instance()->set_priority_op(request_queue::WRITE); // fill the rest of the last block with max values fill_with_max_value(Blocks1, cur_run_size, blocks1_length); for (i = 0; i < cur_run_size; ++i) { run[i].value = Blocks1[i][0]; write_reqs[i] = Blocks1[i].write(run[i].bid); } result_.runs.push_back(run); result_.runs_sizes.push_back(blocks1_length); result_.elements += blocks1_length; if (input.empty()) { // return wait_all(write_reqs, write_reqs + cur_run_size); delete[] write_reqs; delete[] Blocks1; return; } STXXL_VERBOSE1("Filling the second part of the allocated blocks"); blocks2_length = fetch(Blocks2, 0, el_in_run); if (input.empty()) { // optimization if the whole set fits into both halves // (re)sort internally and return blocks2_length += el_in_run; sort_run(Blocks1, blocks2_length); // sort first an second run together wait_all(write_reqs, write_reqs + cur_run_size); bm->delete_blocks(make_bid_iterator(run.begin()), make_bid_iterator(run.end())); cur_run_size = div_ceil(blocks2_length, block_type::size); run.resize(cur_run_size); bm->new_blocks(AllocStr_(), make_bid_iterator(run.begin()), make_bid_iterator(run.end())); // fill the rest of the last block with max values fill_with_max_value(Blocks1, cur_run_size, blocks2_length); assert(cur_run_size > m2); for (i = 0; i < m2; ++i) { run[i].value = Blocks1[i][0]; write_reqs[i]->wait(); write_reqs[i] = Blocks1[i].write(run[i].bid); } request_ptr * write_reqs1 = new request_ptr[cur_run_size - m2]; for ( ; i < cur_run_size; ++i) { run[i].value = Blocks1[i][0]; write_reqs1[i - m2] = Blocks1[i].write(run[i].bid); } result_.runs[0] = run; result_.runs_sizes[0] = blocks2_length; result_.elements = blocks2_length; wait_all(write_reqs, write_reqs + m2); delete[] write_reqs; wait_all(write_reqs1, write_reqs1 + cur_run_size - m2); delete[] write_reqs1; delete[] Blocks1; return; } // more than 2 runs can be filled, i. e. the general case sort_run(Blocks2, blocks2_length); cur_run_size = div_ceil(blocks2_length, block_type::size); // in blocks run.resize(cur_run_size); bm->new_blocks(AllocStr_(), make_bid_iterator(run.begin()), make_bid_iterator(run.end())); for (i = 0; i < cur_run_size; ++i) { run[i].value = Blocks2[i][0]; write_reqs[i]->wait(); write_reqs[i] = Blocks2[i].write(run[i].bid); } assert((blocks2_length % el_in_run) == 0); result_.runs.push_back(run); result_.runs_sizes.push_back(blocks2_length); result_.elements += blocks2_length; while (!input.empty()) { blocks1_length = fetch(Blocks1, 0, el_in_run); sort_run(Blocks1, blocks1_length); cur_run_size = div_ceil(blocks1_length, block_type::size); // in blocks run.resize(cur_run_size); bm->new_blocks(AllocStr_(), make_bid_iterator(run.begin()), make_bid_iterator(run.end())); // fill the rest of the last block with max values (occurs only on the last run) fill_with_max_value(Blocks1, cur_run_size, blocks1_length); for (i = 0; i < cur_run_size; ++i) { run[i].value = Blocks1[i][0]; write_reqs[i]->wait(); write_reqs[i] = Blocks1[i].write(run[i].bid); } result_.runs.push_back(run); result_.runs_sizes.push_back(blocks1_length); result_.elements += blocks1_length; std::swap(Blocks1, Blocks2); std::swap(blocks1_length, blocks2_length); } wait_all(write_reqs, write_reqs + m2); delete[] write_reqs; delete[] ((Blocks1 < Blocks2) ? Blocks1 : Blocks2); } //! \brief Forms sorted runs of data from a stream //! //! \tparam Input_ type of the input stream //! \tparam Cmp_ type of omparison object used for sorting the runs //! \tparam BlockSize_ size of blocks used to store the runs //! \tparam AllocStr_ functor that defines allocation strategy for the runs template < class Input_, class Cmp_, unsigned BlockSize_ = STXXL_DEFAULT_BLOCK_SIZE(typename Input_::value_type), class AllocStr_ = STXXL_DEFAULT_ALLOC_STRATEGY> class runs_creator : public basic_runs_creator { private: typedef basic_runs_creator base; public: typedef typename base::block_type block_type; private: using base::input; public: //! \brief Creates the object //! \param i input stream //! \param c comparator object //! \param memory_to_use memory amount that is allowed to used by the sorter in bytes runs_creator(Input_ & i, Cmp_ c, unsigned_type memory_to_use) : base(i, c, memory_to_use) { } }; //! \brief Input strategy for \c runs_creator class //! //! This strategy together with \c runs_creator class //! allows to create sorted runs //! data structure usable for \c runs_merger //! pushing elements into the sorter //! (using runs_creator::push()) template struct use_push { typedef ValueType_ value_type; }; //! \brief Forms sorted runs of elements passed in push() method //! //! A specialization of \c runs_creator that //! allows to create sorted runs //! data structure usable for \c runs_merger from //! elements passed in sorted push() method.
//! \tparam ValueType_ type of values (parameter for \c use_push strategy) //! \tparam Cmp_ type of comparison object used for sorting the runs //! \tparam BlockSize_ size of blocks used to store the runs //! \tparam AllocStr_ functor that defines allocation strategy for the runs template < class ValueType_, class Cmp_, unsigned BlockSize_, class AllocStr_> class runs_creator< use_push, Cmp_, BlockSize_, AllocStr_> : private noncopyable { Cmp_ cmp; public: typedef Cmp_ cmp_type; typedef ValueType_ value_type; typedef typed_block block_type; typedef sort_helper::trigger_entry trigger_entry_type; typedef sorted_runs sorted_runs_type; typedef sorted_runs_type result_type; private: typedef typename sorted_runs_type::run_type run_type; sorted_runs_type result_; // stores the result (sorted runs) unsigned_type m_; // memory for internal use in blocks bool result_computed; // true after the result() method was called for the first time const unsigned_type m2; const unsigned_type el_in_run; unsigned_type cur_el; block_type * Blocks1; block_type * Blocks2; request_ptr * write_reqs; run_type run; void fill_with_max_value(block_type * blocks, unsigned_type num_blocks, unsigned_type first_idx) { unsigned_type last_idx = num_blocks * block_type::size; if (first_idx < last_idx) { typename element_iterator_traits::element_iterator curr = make_element_iterator(blocks, first_idx); while (first_idx != last_idx) { *curr = cmp.max_value(); ++curr; ++first_idx; } } } void sort_run(block_type * run, unsigned_type elements) { potentially_parallel:: sort(make_element_iterator(run, 0), make_element_iterator(run, elements), cmp); } void compute_result() { if (cur_el == 0) return; unsigned_type cur_el_reg = cur_el; sort_run(Blocks1, cur_el_reg); result_.elements += cur_el_reg; if (cur_el_reg <= block_type::size && result_.elements == cur_el_reg) { // small input, do not flush it on the disk(s) STXXL_VERBOSE1("runs_creator(use_push): Small input optimization, input length: " << cur_el_reg); result_.small_.resize(cur_el_reg); std::copy(Blocks1[0].begin(), Blocks1[0].begin() + cur_el_reg, result_.small_.begin()); return; } const unsigned_type cur_run_size = div_ceil(cur_el_reg, block_type::size); // in blocks run.resize(cur_run_size); block_manager * bm = block_manager::get_instance(); bm->new_blocks(AllocStr_(), make_bid_iterator(run.begin()), make_bid_iterator(run.end())); disk_queues::get_instance()->set_priority_op(request_queue::WRITE); result_.runs_sizes.push_back(cur_el_reg); // fill the rest of the last block with max values fill_with_max_value(Blocks1, cur_run_size, cur_el_reg); unsigned_type i = 0; for ( ; i < cur_run_size; ++i) { run[i].value = Blocks1[i][0]; if (write_reqs[i].get()) write_reqs[i]->wait(); write_reqs[i] = Blocks1[i].write(run[i].bid); } result_.runs.push_back(run); for (i = 0; i < m2; ++i) if (write_reqs[i].get()) write_reqs[i]->wait(); } void cleanup() { delete[] write_reqs; delete[] ((Blocks1 < Blocks2) ? Blocks1 : Blocks2); write_reqs = NULL; Blocks1 = Blocks2 = NULL; } public: //! \brief Creates the object //! \param c comparator object //! \param memory_to_use memory amount that is allowed to used by the sorter in bytes runs_creator(Cmp_ c, unsigned_type memory_to_use) : cmp(c), m_(memory_to_use / BlockSize_ / sort_memory_usage_factor()), result_computed(false), m2(m_ / 2), el_in_run(m2 * block_type::size), cur_el(0), Blocks1(new block_type[m2 * 2]), Blocks2(Blocks1 + m2), write_reqs(new request_ptr[m2]) { sort_helper::verify_sentinel_strict_weak_ordering(cmp); if (!(2 * BlockSize_ * sort_memory_usage_factor() <= memory_to_use)) { throw bad_parameter("stxxl::runs_creator<>:runs_creator(): INSUFFICIENT MEMORY provided, please increase parameter 'memory_to_use'"); } assert(m2 > 0); } ~runs_creator() { if (!result_computed) cleanup(); } //! \brief Adds new element to the sorter //! \param val value to be added void push(const value_type & val) { assert(result_computed == false); unsigned_type cur_el_reg = cur_el; if (cur_el_reg < el_in_run) { Blocks1[cur_el_reg / block_type::size][cur_el_reg % block_type::size] = val; ++cur_el; return; } assert(el_in_run == cur_el); cur_el = 0; //sort and store Blocks1 sort_run(Blocks1, el_in_run); result_.elements += el_in_run; const unsigned_type cur_run_size = div_ceil(el_in_run, block_type::size); // in blocks run.resize(cur_run_size); block_manager * bm = block_manager::get_instance(); bm->new_blocks(AllocStr_(), make_bid_iterator(run.begin()), make_bid_iterator(run.end())); disk_queues::get_instance()->set_priority_op(request_queue::WRITE); result_.runs_sizes.push_back(el_in_run); for (unsigned_type i = 0; i < cur_run_size; ++i) { run[i].value = Blocks1[i][0]; if (write_reqs[i].get()) write_reqs[i]->wait(); write_reqs[i] = Blocks1[i].write(run[i].bid); } result_.runs.push_back(run); std::swap(Blocks1, Blocks2); push(val); } //! \brief Returns the sorted runs object //! \return Sorted runs object. //! \remark Returned object is intended to be used by \c runs_merger object as input const sorted_runs_type & result() { if (1) { if (!result_computed) { compute_result(); result_computed = true; cleanup(); #ifdef STXXL_PRINT_STAT_AFTER_RF STXXL_MSG(*stats::get_instance()); #endif //STXXL_PRINT_STAT_AFTER_RF } } return result_; } }; //! \brief Input strategy for \c runs_creator class //! //! This strategy together with \c runs_creator class //! allows to create sorted runs //! data structure usable for \c runs_merger from //! sequences of elements in sorted order template struct from_sorted_sequences { typedef ValueType_ value_type; }; //! \brief Forms sorted runs of data taking elements in sorted order (element by element) //! //! A specialization of \c runs_creator that //! allows to create sorted runs //! data structure usable for \c runs_merger from //! sequences of elements in sorted order.
//! \tparam ValueType_ type of values (parameter for \c from_sorted_sequences strategy) //! \tparam Cmp_ type of comparison object used for sorting the runs //! \tparam BlockSize_ size of blocks used to store the runs //! \tparam AllocStr_ functor that defines allocation strategy for the runs template < class ValueType_, class Cmp_, unsigned BlockSize_, class AllocStr_> class runs_creator< from_sorted_sequences, Cmp_, BlockSize_, AllocStr_> : private noncopyable { typedef ValueType_ value_type; typedef typed_block block_type; typedef sort_helper::trigger_entry trigger_entry_type; typedef AllocStr_ alloc_strategy_type; Cmp_ cmp; public: typedef Cmp_ cmp_type; typedef sorted_runs sorted_runs_type; typedef sorted_runs_type result_type; private: typedef typename sorted_runs_type::run_type run_type; sorted_runs_type result_; // stores the result (sorted runs) unsigned_type m_; // memory for internal use in blocks buffered_writer writer; block_type * cur_block; unsigned_type offset; unsigned_type iblock; unsigned_type irun; alloc_strategy_type alloc_strategy; // needs to be reset after each run public: //! \brief Creates the object //! \param c comparator object //! \param memory_to_use memory amount that is allowed to used by the sorter in bytes. //! Recommended value: 2 * block_size * D runs_creator(Cmp_ c, unsigned_type memory_to_use) : cmp(c), m_(memory_to_use / BlockSize_ / sort_memory_usage_factor()), writer(m_, m_ / 2), cur_block(writer.get_free_block()), offset(0), iblock(0), irun(0) { sort_helper::verify_sentinel_strict_weak_ordering(cmp); assert(m_ > 0); if (!(2 * BlockSize_ * sort_memory_usage_factor() <= memory_to_use)) { throw bad_parameter("stxxl::runs_creator<>:runs_creator(): INSUFFICIENT MEMORY provided, please increase parameter 'memory_to_use'"); } } //! \brief Adds new element to the current run //! \param val value to be added to the current run void push(const value_type & val) { assert(offset < block_type::size); (*cur_block)[offset] = val; ++offset; if (offset == block_type::size) { // write current block block_manager * bm = block_manager::get_instance(); // allocate space for the block result_.runs.resize(irun + 1); result_.runs[irun].resize(iblock + 1); bm->new_blocks( alloc_strategy, make_bid_iterator(result_.runs[irun].begin() + iblock), make_bid_iterator(result_.runs[irun].end()), iblock ); result_.runs[irun][iblock].value = (*cur_block)[0]; // init trigger cur_block = writer.write(cur_block, result_.runs[irun][iblock].bid); ++iblock; offset = 0; } ++result_.elements; } //! \brief Finishes current run and begins new one void finish() { if (offset == 0 && iblock == 0) // current run is empty return; result_.runs_sizes.resize(irun + 1); result_.runs_sizes.back() = iblock * block_type::size + offset; if (offset) // if current block is partially filled { while (offset != block_type::size) { (*cur_block)[offset] = cmp.max_value(); ++offset; } offset = 0; block_manager * bm = block_manager::get_instance(); // allocate space for the block result_.runs.resize(irun + 1); result_.runs[irun].resize(iblock + 1); bm->new_blocks( alloc_strategy, make_bid_iterator(result_.runs[irun].begin() + iblock), make_bid_iterator(result_.runs[irun].end()), iblock ); result_.runs[irun][iblock].value = (*cur_block)[0]; // init trigger cur_block = writer.write(cur_block, result_.runs[irun][iblock].bid); } else { } alloc_strategy = alloc_strategy_type(); // reinitialize block allocator for the next run iblock = 0; ++irun; } //! \brief Returns the sorted runs object //! \return Sorted runs object //! \remark Returned object is intended to be used by \c runs_merger object as input const sorted_runs_type & result() { finish(); writer.flush(); return result_; } }; //! \brief Checker for the sorted runs object created by the \c runs_creator . //! \param sruns sorted runs object //! \param cmp comparison object used for checking the order of elements in runs //! \return \c true if runs are sorted, \c false otherwise template bool check_sorted_runs(const RunsType_ & sruns, Cmp_ cmp) { sort_helper::verify_sentinel_strict_weak_ordering(cmp); typedef typename RunsType_::block_type block_type; typedef typename block_type::value_type value_type; STXXL_VERBOSE2("Elements: " << sruns.elements); unsigned_type nruns = sruns.runs.size(); STXXL_VERBOSE2("Runs: " << nruns); unsigned_type irun = 0; for (irun = 0; irun < nruns; ++irun) { const unsigned_type nblocks = sruns.runs[irun].size(); block_type * blocks = new block_type[nblocks]; request_ptr * reqs = new request_ptr[nblocks]; for (unsigned_type j = 0; j < nblocks; ++j) { reqs[j] = blocks[j].read(sruns.runs[irun][j].bid); } wait_all(reqs, reqs + nblocks); for (unsigned_type j = 0; j < nblocks; ++j) { if (cmp(blocks[j][0], sruns.runs[irun][j].value) || cmp(sruns.runs[irun][j].value, blocks[j][0])) //!= { STXXL_ERRMSG("check_sorted_runs wrong trigger in the run"); return false; } } if (!stxxl::is_sorted(make_element_iterator(blocks, 0), make_element_iterator(blocks, sruns.runs_sizes[irun]), cmp)) { STXXL_ERRMSG("check_sorted_runs wrong order in the run"); return false; } delete[] reqs; delete[] blocks; } STXXL_MSG("Checking runs finished successfully"); return true; } //////////////////////////////////////////////////////////////////////// // MERGE RUNS // //////////////////////////////////////////////////////////////////////// //! \brief Merges sorted runs //! //! \tparam RunsType_ type of the sorted runs, available as \c runs_creator::sorted_runs_type , //! \tparam Cmp_ type of comparison object used for merging //! \tparam AllocStr_ allocation strategy used to allocate the blocks for //! storing intermediate results if several merge passes are required template class basic_runs_merger : private noncopyable { protected: typedef RunsType_ sorted_runs_type; typedef AllocStr_ alloc_strategy; typedef typename sorted_runs_type::size_type size_type; typedef Cmp_ value_cmp; typedef typename sorted_runs_type::run_type run_type; typedef typename sorted_runs_type::block_type block_type; typedef block_type out_block_type; typedef typename run_type::value_type trigger_entry_type; typedef block_prefetcher prefetcher_type; typedef run_cursor2 run_cursor_type; typedef sort_helper::run_cursor2_cmp run_cursor2_cmp_type; typedef loser_tree loser_tree_type; typedef stxxl::int64 diff_type; typedef std::pair sequence; typedef typename std::vector::size_type seqs_size_type; public: //! \brief Standard stream typedef typedef typename sorted_runs_type::value_type value_type; private: sorted_runs_type sruns; value_cmp cmp; size_type elements_remaining; out_block_type * current_block; unsigned_type buffer_pos; value_type current_value; // cache for the current value run_type consume_seq; int_type * prefetch_seq; prefetcher_type * prefetcher; loser_tree_type * losers; #if STXXL_PARALLEL_MULTIWAY_MERGE std::vector * seqs; std::vector * buffers; diff_type num_currently_mergeable; #endif #if STXXL_CHECK_ORDER_IN_SORTS value_type last_element; #endif //STXXL_CHECK_ORDER_IN_SORTS //////////////////////////////////////////////////////////////////// void merge_recursively(unsigned_type memory_to_use); void deallocate_prefetcher() { if (prefetcher) { delete losers; #if STXXL_PARALLEL_MULTIWAY_MERGE delete seqs; delete buffers; #endif delete prefetcher; delete[] prefetch_seq; prefetcher = NULL; } // free blocks in runs , (or the user should do it?) sruns.deallocate_blocks(); } void fill_current_block() { STXXL_VERBOSE1("fill_current_block"); if (do_parallel_merge()) { #if STXXL_PARALLEL_MULTIWAY_MERGE // begin of STL-style merging diff_type rest = out_block_type::size; // elements still to merge for this output block do // while rest > 0 and still elements available { if (num_currently_mergeable < rest) { if (!prefetcher || prefetcher->empty()) { // anything remaining is already in memory num_currently_mergeable = elements_remaining; } else { num_currently_mergeable = sort_helper::count_elements_less_equal( *seqs, consume_seq[prefetcher->pos()].value, cmp); } } diff_type output_size = STXXL_MIN(num_currently_mergeable, rest); // at most rest elements STXXL_VERBOSE1("before merge " << output_size); stxxl::parallel::multiway_merge((*seqs).begin(), (*seqs).end(), current_block->end() - rest, cmp, output_size); // sequence iterators are progressed appropriately rest -= output_size; num_currently_mergeable -= output_size; STXXL_VERBOSE1("after merge"); sort_helper::refill_or_remove_empty_sequences(*seqs, *buffers, *prefetcher); } while (rest > 0 && (*seqs).size() > 0); #if STXXL_CHECK_ORDER_IN_SORTS if (!stxxl::is_sorted(current_block->begin(), current_block->end(), cmp)) { for (value_type * i = current_block->begin() + 1; i != current_block->end(); ++i) if (cmp(*i, *(i - 1))) { STXXL_VERBOSE1("Error at position " << (i - current_block->begin())); } assert(false); } #endif //STXXL_CHECK_ORDER_IN_SORTS // end of STL-style merging #else STXXL_THROW_UNREACHABLE(); #endif //STXXL_PARALLEL_MULTIWAY_MERGE } else { // begin of native merging procedure losers->multi_merge(current_block->elem, current_block->elem + STXXL_MIN(out_block_type::size, elements_remaining)); // end of native merging procedure } STXXL_VERBOSE1("current block filled"); if (elements_remaining <= out_block_type::size) deallocate_prefetcher(); } public: //! \brief Creates a runs merger object //! \param r input sorted runs object //! \param c comparison object //! \param memory_to_use amount of memory available for the merger in bytes basic_runs_merger(const sorted_runs_type & r, value_cmp c, unsigned_type memory_to_use) : sruns(r), cmp(c), elements_remaining(sruns.elements), current_block(NULL), buffer_pos(0), prefetch_seq(NULL), prefetcher(NULL), losers(NULL) #if STXXL_PARALLEL_MULTIWAY_MERGE , seqs(NULL), buffers(NULL), num_currently_mergeable(0) #endif #if STXXL_CHECK_ORDER_IN_SORTS , last_element(cmp.min_value()) #endif //STXXL_CHECK_ORDER_IN_SORTS { initialize(r, memory_to_use); } protected: void initialize(const sorted_runs_type & r, unsigned_type memory_to_use) { sort_helper::verify_sentinel_strict_weak_ordering(cmp); sruns = r; elements_remaining = r.elements; if (empty()) return; if (!sruns.small_run().empty()) { // we have a small input <= B, that is kept in the main memory STXXL_VERBOSE1("basic_runs_merger: small input optimization, input length: " << elements_remaining); assert(elements_remaining == size_type(sruns.small_run().size())); assert(sruns.small_run().size() <= out_block_type::size); current_block = new out_block_type; std::copy(sruns.small_run().begin(), sruns.small_run().end(), current_block->begin()); current_value = current_block->elem[0]; buffer_pos = 1; return; } #if STXXL_CHECK_ORDER_IN_SORTS assert(check_sorted_runs(r, cmp)); #endif //STXXL_CHECK_ORDER_IN_SORTS disk_queues::get_instance()->set_priority_op(request_queue::WRITE); int_type disks_number = config::get_instance()->disks_number(); unsigned_type min_prefetch_buffers = 2 * disks_number; unsigned_type input_buffers = (memory_to_use > sizeof(out_block_type) ? memory_to_use - sizeof(out_block_type) : 0) / block_type::raw_size; unsigned_type nruns = sruns.runs.size(); if (input_buffers < nruns + min_prefetch_buffers) { // can not merge runs in one pass // merge recursively: STXXL_WARNMSG_RECURSIVE_SORT("The implementation of sort requires more than one merge pass, therefore for a better"); STXXL_WARNMSG_RECURSIVE_SORT("efficiency decrease block size of run storage (a parameter of the run_creator)"); STXXL_WARNMSG_RECURSIVE_SORT("or increase the amount memory dedicated to the merger."); STXXL_WARNMSG_RECURSIVE_SORT("m=" << input_buffers << " nruns=" << nruns << " prefetch_blocks=" << min_prefetch_buffers); // check whether we have enough memory to merge recursively unsigned_type recursive_merge_buffers = memory_to_use / block_type::raw_size; if (recursive_merge_buffers < 2 * min_prefetch_buffers + 1 + 2) { // recursive merge uses min_prefetch_buffers for input buffering and min_prefetch_buffers output buffering // as well as 1 current output block and at least 2 input blocks STXXL_ERRMSG("There are only m=" << recursive_merge_buffers << " blocks available for recursive merging, but " << min_prefetch_buffers << "+" << min_prefetch_buffers << "+1 are needed read-ahead/write-back/output, and"); STXXL_ERRMSG("the merger requires memory to store at least two input blocks internally. Aborting."); throw bad_parameter("basic_runs_merger::sort(): INSUFFICIENT MEMORY provided, please increase parameter 'memory_to_use'"); } merge_recursively(memory_to_use); nruns = sruns.runs.size(); } assert(nruns + min_prefetch_buffers <= input_buffers); unsigned_type i; unsigned_type prefetch_seq_size = 0; for (i = 0; i < nruns; ++i) { prefetch_seq_size += sruns.runs[i].size(); } consume_seq.resize(prefetch_seq_size); prefetch_seq = new int_type[prefetch_seq_size]; typename run_type::iterator copy_start = consume_seq.begin(); for (i = 0; i < nruns; ++i) { copy_start = std::copy( sruns.runs[i].begin(), sruns.runs[i].end(), copy_start); } std::stable_sort(consume_seq.begin(), consume_seq.end(), sort_helper::trigger_entry_cmp(cmp) _STXXL_SORT_TRIGGER_FORCE_SEQUENTIAL); const unsigned_type n_prefetch_buffers = STXXL_MAX(min_prefetch_buffers, input_buffers - nruns); #if STXXL_SORT_OPTIMAL_PREFETCHING // heuristic const int_type n_opt_prefetch_buffers = min_prefetch_buffers + (3 * (n_prefetch_buffers - min_prefetch_buffers)) / 10; compute_prefetch_schedule( consume_seq, prefetch_seq, n_opt_prefetch_buffers, disks_number); #else for (i = 0; i < prefetch_seq_size; ++i) prefetch_seq[i] = i; #endif //STXXL_SORT_OPTIMAL_PREFETCHING prefetcher = new prefetcher_type( consume_seq.begin(), consume_seq.end(), prefetch_seq, STXXL_MIN(nruns + n_prefetch_buffers, prefetch_seq_size)); if (do_parallel_merge()) { #if STXXL_PARALLEL_MULTIWAY_MERGE // begin of STL-style merging seqs = new std::vector(nruns); buffers = new std::vector(nruns); for (unsigned_type i = 0; i < nruns; ++i) //initialize sequences { (*buffers)[i] = prefetcher->pull_block(); //get first block of each run (*seqs)[i] = std::make_pair((*buffers)[i]->begin(), (*buffers)[i]->end()); //this memory location stays the same, only the data is exchanged } // end of STL-style merging #else STXXL_THROW_UNREACHABLE(); #endif //STXXL_PARALLEL_MULTIWAY_MERGE } else { // begin of native merging procedure losers = new loser_tree_type(prefetcher, nruns, run_cursor2_cmp_type(cmp)); // end of native merging procedure } current_block = new out_block_type; fill_current_block(); current_value = current_block->elem[0]; buffer_pos = 1; } public: //! \brief Standard stream method bool empty() const { return elements_remaining == 0; } //! \brief Standard stream method const value_type & operator * () const { assert(!empty()); return current_value; } //! \brief Standard stream method const value_type * operator -> () const { return &(operator * ()); } //! \brief Standard stream method basic_runs_merger & operator ++ () // preincrement operator { assert(!empty()); --elements_remaining; if (buffer_pos != out_block_type::size) { current_value = current_block->elem[buffer_pos]; ++buffer_pos; } else { if (!empty()) { fill_current_block(); #if STXXL_CHECK_ORDER_IN_SORTS assert(stxxl::is_sorted(current_block->elem, current_block->elem + STXXL_MIN(elements_remaining, current_block->size), cmp)); assert(!cmp(current_block->elem[0], current_value)); #endif //STXXL_CHECK_ORDER_IN_SORTS current_value = current_block->elem[0]; buffer_pos = 1; } } #if STXXL_CHECK_ORDER_IN_SORTS if (!empty()) { assert(!cmp(current_value, last_element)); last_element = current_value; } #endif //STXXL_CHECK_ORDER_IN_SORTS return *this; } //! \brief Destructor //! \remark Deallocates blocks of the input sorted runs object virtual ~basic_runs_merger() { deallocate_prefetcher(); delete current_block; } }; template void basic_runs_merger::merge_recursively(unsigned_type memory_to_use) { block_manager * bm = block_manager::get_instance(); unsigned_type ndisks = config::get_instance()->disks_number(); unsigned_type nwrite_buffers = 2 * ndisks; unsigned_type memory_for_write_buffers = nwrite_buffers * sizeof(block_type); // memory consumption of the recursive merger (uses block_type as out_block_type) unsigned_type recursive_merger_memory_prefetch_buffers = 2 * ndisks * sizeof(block_type); unsigned_type recursive_merger_memory_out_block = sizeof(block_type); unsigned_type memory_for_buffers = memory_for_write_buffers + recursive_merger_memory_prefetch_buffers + recursive_merger_memory_out_block; // maximum arity in the recursive merger unsigned_type max_arity = (memory_to_use > memory_for_buffers ? memory_to_use - memory_for_buffers : 0) / block_type::raw_size; unsigned_type nruns = sruns.runs.size(); const unsigned_type merge_factor = optimal_merge_factor(nruns, max_arity); assert(merge_factor > 1); assert(merge_factor <= max_arity); while (nruns > max_arity) { unsigned_type new_nruns = div_ceil(nruns, merge_factor); STXXL_VERBOSE("Starting new merge phase: nruns: " << nruns << " opt_merge_factor: " << merge_factor << " max_arity: " << max_arity << " new_nruns: " << new_nruns); sorted_runs_type new_runs; new_runs.runs.resize(new_nruns); new_runs.runs_sizes.resize(new_nruns); new_runs.elements = sruns.elements; unsigned_type runs_left = nruns; unsigned_type cur_out_run = 0; unsigned_type elements_in_new_run = 0; while (runs_left > 0) { int_type runs2merge = STXXL_MIN(runs_left, merge_factor); elements_in_new_run = 0; for (unsigned_type i = nruns - runs_left; i < (nruns - runs_left + runs2merge); ++i) { elements_in_new_run += sruns.runs_sizes[i]; } const unsigned_type blocks_in_new_run1 = div_ceil(elements_in_new_run, block_type::size); new_runs.runs_sizes[cur_out_run] = elements_in_new_run; // allocate run new_runs.runs[cur_out_run++].resize(blocks_in_new_run1); runs_left -= runs2merge; } // allocate blocks for the new runs for (unsigned_type i = 0; i < new_runs.runs.size(); ++i) bm->new_blocks(alloc_strategy(), make_bid_iterator(new_runs.runs[i].begin()), make_bid_iterator(new_runs.runs[i].end())); // merge all runs_left = nruns; cur_out_run = 0; size_type elements_left = sruns.elements; while (runs_left > 0) { unsigned_type runs2merge = STXXL_MIN(runs_left, merge_factor); STXXL_VERBOSE("Merging " << runs2merge << " runs"); sorted_runs_type cur_runs; cur_runs.runs.resize(runs2merge); cur_runs.runs_sizes.resize(runs2merge); std::copy(sruns.runs.begin() + nruns - runs_left, sruns.runs.begin() + nruns - runs_left + runs2merge, cur_runs.runs.begin()); std::copy(sruns.runs_sizes.begin() + nruns - runs_left, sruns.runs_sizes.begin() + nruns - runs_left + runs2merge, cur_runs.runs_sizes.begin()); runs_left -= runs2merge; /* cur_runs.elements = (runs_left)? (new_runs.runs[cur_out_run].size()*block_type::size): (elements_left); */ cur_runs.elements = new_runs.runs_sizes[cur_out_run]; elements_left -= cur_runs.elements; if (runs2merge > 1) { basic_runs_merger merger(cur_runs, cmp, memory_to_use - memory_for_write_buffers); { // make sure everything is being destroyed in right time buf_ostream out( new_runs.runs[cur_out_run].begin(), nwrite_buffers); size_type cnt = 0; const size_type cnt_max = cur_runs.elements; while (cnt != cnt_max) { *out = *merger; if ((cnt % block_type::size) == 0) // have to write the trigger value new_runs.runs[cur_out_run][cnt / size_type(block_type::size)].value = *merger; ++cnt; ++out; ++merger; } assert(merger.empty()); while (cnt % block_type::size) { *out = cmp.max_value(); ++out; ++cnt; } } } else { bm->delete_blocks( make_bid_iterator(new_runs.runs.back().begin()), make_bid_iterator(new_runs.runs.back().end())); assert(cur_runs.runs.size() == 1); std::copy(cur_runs.runs.front().begin(), cur_runs.runs.front().end(), new_runs.runs.back().begin()); new_runs.runs_sizes.back() = cur_runs.runs_sizes.front(); } ++cur_out_run; } assert(elements_left == 0); nruns = new_nruns; sruns = new_runs; } } //! \brief Merges sorted runs //! //! \tparam RunsType_ type of the sorted runs, available as \c runs_creator::sorted_runs_type , //! \tparam Cmp_ type of comparison object used for merging //! \tparam AllocStr_ allocation strategy used to allocate the blocks for //! storing intermediate results if several merge passes are required template class runs_merger : public basic_runs_merger { private: typedef RunsType_ sorted_runs_type; typedef basic_runs_merger base; typedef typename base::value_cmp value_cmp; typedef typename base::block_type block_type; public: //! \brief Creates a runs merger object //! \param r input sorted runs object //! \param c comparison object //! \param memory_to_use amount of memory available for the merger in bytes runs_merger(const sorted_runs_type & r, value_cmp c, unsigned_type memory_to_use) : base(r, c, memory_to_use) { } }; //////////////////////////////////////////////////////////////////////// // SORT // //////////////////////////////////////////////////////////////////////// //! \brief Produces sorted stream from input stream //! //! \tparam Input_ type of the input stream //! \tparam Cmp_ type of comparison object used for sorting the runs //! \tparam BlockSize_ size of blocks used to store the runs //! \tparam AllocStr_ functor that defines allocation strategy for the runs //! \remark Implemented as the composition of \c runs_creator and \c runs_merger . template > class sort : public noncopyable { typedef typename runs_creator_type::sorted_runs_type sorted_runs_type; typedef runs_merger runs_merger_type; runs_creator_type creator; runs_merger_type merger; public: //! \brief Standard stream typedef typedef typename Input_::value_type value_type; //! \brief Creates the object //! \param in input stream //! \param c comparator object //! \param memory_to_use memory amount that is allowed to used by the sorter in bytes sort(Input_ & in, Cmp_ c, unsigned_type memory_to_use) : creator(in, c, memory_to_use), merger(creator.result(), c, memory_to_use) { sort_helper::verify_sentinel_strict_weak_ordering(c); } //! \brief Creates the object //! \param in input stream //! \param c comparator object //! \param memory_to_use_rc memory amount that is allowed to used by the runs creator in bytes //! \param memory_to_use_m memory amount that is allowed to used by the merger in bytes sort(Input_ & in, Cmp_ c, unsigned_type memory_to_use_rc, unsigned_type memory_to_use_m) : creator(in, c, memory_to_use_rc), merger(creator.result(), c, memory_to_use_m) { sort_helper::verify_sentinel_strict_weak_ordering(c); } //! \brief Standard stream method bool empty() const { return merger.empty(); } //! \brief Standard stream method const value_type & operator * () const { assert(!empty()); return *merger; } const value_type * operator -> () const { assert(!empty()); return merger.operator -> (); } //! \brief Standard stream method sort & operator ++ () { ++merger; return *this; } }; //! \brief Computes sorted runs type from value type and block size //! //! \tparam ValueType_ type of values ins sorted runs //! \tparam BlockSize_ size of blocks where sorted runs stored template < class ValueType_, unsigned BlockSize_> class compute_sorted_runs_type { typedef ValueType_ value_type; typedef BID bid_type; typedef sort_helper::trigger_entry trigger_entry_type; public: typedef sorted_runs result; }; //! \} } //! \addtogroup stlalgo //! \{ //! \brief Sorts range of any random access iterators externally //! \param begin iterator pointing to the first element of the range //! \param end iterator pointing to the last+1 element of the range //! \param cmp comparison object //! \param MemSize memory to use for sorting (in bytes) //! \param AS allocation strategy //! //! The \c BlockSize template parameter defines the block size to use (in bytes) //! \warning Slower than External Iterator Sort template void sort(RandomAccessIterator begin, RandomAccessIterator end, CmpType cmp, unsigned_type MemSize, AllocStr AS) { STXXL_UNUSED(AS); #ifdef BOOST_MSVC typedef typename streamify_traits::stream_type InputType; #else typedef __typeof__(stream::streamify(begin, end)) InputType; #endif //BOOST_MSVC InputType Input(begin, end); typedef stream::sort sorter_type; sorter_type Sort(Input, cmp, MemSize); stream::materialize(Sort, begin); } //! \} __STXXL_END_NAMESPACE #endif // !STXXL_SORT_STREAM_HEADER // vim: et:ts=4:sw=4 stxxl-1.3.1/include/stxxl/bits/stream/unique.h0000644000175000017500000000713111513611117021231 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/stream/unique.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2003-2005 Roman Dementiev * Copyright (C) 2010 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_STREAM__UNIQUE_H #define STXXL_STREAM__UNIQUE_H #include __STXXL_BEGIN_NAMESPACE //! \brief Stream package subnamespace namespace stream { //////////////////////////////////////////////////////////////////////// // UNIQUE // //////////////////////////////////////////////////////////////////////// struct dummy_cmp_unique_ { }; //! \brief Equivalent to std::unique algorithms //! //! Removes consecutive duplicates from the stream. //! Uses BinaryPredicate to compare elements of the stream template class unique { Input & input; BinaryPredicate binary_pred; typename Input::value_type current; public: //! \brief Standard stream typedef typedef typename Input::value_type value_type; unique(Input & input_, BinaryPredicate binary_pred_) : input(input_), binary_pred(binary_pred_) { if (!input.empty()) current = *input; } //! \brief Standard stream method unique & operator ++ () { value_type old_value = current; ++input; while (!input.empty() && (binary_pred(current = *input, old_value))) ++input; return *this; } //! \brief Standard stream method const value_type & operator * () const { return current; } //! \brief Standard stream method const value_type * operator -> () const { return ¤t; } //! \brief Standard stream method bool empty() const { return input.empty(); } }; //! \brief Equivalent to std::unique algorithms //! //! Removes consecutive duplicates from the stream. template class unique { Input & input; typename Input::value_type current; public: //! \brief Standard stream typedef typedef typename Input::value_type value_type; unique(Input & input_) : input(input_) { if (!input.empty()) current = *input; } //! \brief Standard stream method unique & operator ++ () { value_type old_value = current; ++input; while (!input.empty() && ((current = *input) == old_value)) ++input; return *this; } //! \brief Standard stream method const value_type & operator * () const { return current; } //! \brief Standard stream method const value_type * operator -> () const { return ¤t; } //! \brief Standard stream method bool empty() const { return input.empty(); } }; //! \} } __STXXL_END_NAMESPACE #endif // !STXXL_STREAM__UNIQUE_H // vim: et:ts=4:sw=4 stxxl-1.3.1/include/stxxl/bits/stream/sorted_runs.h0000644000175000017500000000562111535151017022276 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/stream/sorted_runs.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2002-2005 Roman Dementiev * Copyright (C) 2009, 2010 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_STREAM__SORTED_RUNS_H #define STXXL_STREAM__SORTED_RUNS_H #include #include #include #include __STXXL_BEGIN_NAMESPACE namespace stream { //! \addtogroup streampack Stream package //! \{ //////////////////////////////////////////////////////////////////////// // SORTED RUNS // //////////////////////////////////////////////////////////////////////// //! \brief All sorted runs of a sort operation. template struct sorted_runs { typedef TriggerEntryType trigger_entry_type; typedef typename trigger_entry_type::block_type block_type; typedef typename block_type::value_type value_type; // may differ from trigger_entry_type::value_type typedef std::vector run_type; typedef std::vector small_run_type; typedef stxxl::external_size_type size_type; typedef typename std::vector::size_type run_index_type; size_type elements; std::vector runs; std::vector runs_sizes; // Optimization: // if the input is small such that its total size is // at most B (block_type::size) // then input is sorted internally // and kept in the array "small" small_run_type small_; sorted_runs() : elements(0) { } const small_run_type & small_run() const { return small_; } //! \brief Deallocates the blocks which the runs occupy //! //! \remark Usually there is no need in calling this method, //! since the \c runs_merger calls it when it is being destructed void deallocate_blocks() { block_manager * bm = block_manager::get_instance(); for (unsigned_type i = 0; i < runs.size(); ++i) bm->delete_blocks(make_bid_iterator(runs[i].begin()), make_bid_iterator(runs[i].end())); runs.clear(); } // returns number of elements in all runs together size_type size() const { return elements; } }; //! \} } __STXXL_END_NAMESPACE #endif // !STXXL_STREAM__SORTED_RUNS_H // vim: et:ts=4:sw=4 stxxl-1.3.1/include/stxxl/bits/noncopyable.h0000644000175000017500000000205211024506746020746 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/noncopyable.h * * Inspired by boost::noncopyable. * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2007 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_NONCOPYABLE_HEADER #define STXXL_NONCOPYABLE_HEADER #ifdef STXXL_BOOST_CONFIG #include #endif #include __STXXL_BEGIN_NAMESPACE #ifdef STXXL_BOOST_CONFIG typedef boost::noncopyable noncopyable; #else class noncopyable { protected: noncopyable() { } private: // copying and assignment is not allowed noncopyable(const noncopyable &); const noncopyable & operator = (const noncopyable &); }; #endif __STXXL_END_NAMESPACE #endif // !STXXL_NONCOPYABLE_HEADER stxxl-1.3.1/include/stxxl/bits/libstxxl.h0000644000175000017500000000137511517324743020317 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/libstxxl.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2011 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_LIBSTXXL_H #define STXXL_LIBSTXXL_H #ifdef STXXL_BOOST_CONFIG #include #endif #ifdef BOOST_MSVC #ifndef STXXL_LIBNAME #define STXXL_LIBNAME "stxxl" #endif #pragma comment (lib, "lib" STXXL_LIBNAME ".lib") #endif #endif // !STXXL_IO_HEADER stxxl-1.3.1/include/stxxl/bits/utils/0000755000175000017500000000000011536252421017421 5ustar andreasandreasstxxl-1.3.1/include/stxxl/bits/utils/malloc.h0000644000175000017500000001132111531445437021045 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/utils/malloc.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2003 Roman Dementiev * Copyright (C) 2009 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_MALLOC_H #define STXXL_MALLOC_H #include #ifdef __FreeBSD__ #include #else #include #endif #include #include __STXXL_BEGIN_NAMESPACE //! \brief Access to some useful malloc statistics //! malloc is default C++ allocator class malloc_stats { #if !defined(__APPLE__) && !defined(__FreeBSD__) public: typedef int return_type; //! \brief Returns number of bytes allocated from system not including mmapped regions return_type from_system_nmmap() const { struct mallinfo info = mallinfo(); return info.arena; } //! \brief Returns number of free chunks return_type free_chunks() const { struct mallinfo info = mallinfo(); return info.ordblks; } //! \brief Number of bytes allocated and in use return_type used() const { struct mallinfo info = mallinfo(); return info.uordblks; } //! \brief Number of bytes allocated but not in use return_type not_used() const { struct mallinfo info = mallinfo(); return info.fordblks; } //! \brief Top-most, releasable (via malloc_trim) space (bytes) return_type releasable() const { struct mallinfo info = mallinfo(); return info.keepcost; } //! \brief Maximum total allocated space (bytes) (always 0 ?) return_type max_allocated() const { struct mallinfo info = mallinfo(); return info.usmblks; } //! \brief Number of fastbin blocks return_type fastbin_blocks() const { struct mallinfo info = mallinfo(); return info.smblks; } //! \brief Space available in freed fastbin blocks (bytes) return_type fastbin_free() const { struct mallinfo info = mallinfo(); return info.fsmblks; } //! \brief Returns number of bytes allocated from system using mmap return_type from_system_mmap() const { struct mallinfo info = mallinfo(); return info.hblkhd; } //! \brief Number of chunks allocated via mmap() return_type mmap_chunks() const { struct mallinfo info = mallinfo(); return info.hblks; } //! \brief Returns \b total number of bytes allocated from system including mmapped regions return_type from_system_total() const { return from_system_nmmap() + from_system_mmap(); } #endif }; //! \brief Prints current malloc statistics in a convenient way inline std::ostream & operator << (std::ostream & s, const malloc_stats & st) { #if !defined(__APPLE__) && !defined(__FreeBSD__) s << "MALLOC statistics" << std::endl; s << "=================================================================" << std::endl; s << "Space allocated from system not using mmap: " << st.from_system_nmmap() << " bytes" << std::endl; s << " number of free chunks : " << st.free_chunks() << std::endl; s << " space allocated and in use : " << st.used() << " bytes" << std::endl; s << " space allocated but not in use : " << st.not_used() << " bytes" << std::endl; s << " top-most, releasable (via malloc_trim) space: " << st.releasable() << " bytes" << std::endl; s << " maximum total allocated space (?) : " << st.max_allocated() << " bytes" << std::endl; s << " FASTBIN blocks " << std::endl; s << " number of fastbin blocks: " << st.fastbin_blocks() << std::endl; s << " space available in freed fastbin blocks: " << st.fastbin_free() << " bytes" << std::endl; s << "Space allocated from system using mmap: " << st.from_system_mmap() << " bytes" << std::endl; s << " number of chunks allocated via mmap(): " << st.mmap_chunks() << std::endl; s << "Total space allocated from system (mmap and not mmap): " << st.from_system_total() << " bytes" << std::endl; s << "=================================================================" << std::endl; #else s << "MALLOC statistics are not supported on this platform"; STXXL_UNUSED(st); #endif return s; } class malloc_setup { }; __STXXL_END_NAMESPACE #endif // !STXXL_MALLOC_H stxxl-1.3.1/include/stxxl/bits/defines.h0000644000175000017500000000617711535571033020064 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/defines.h * * Document all defines that may change the behavior of stxxl. * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2008-2010 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_DEFINES_HEADER #define STXXL_DEFINES_HEADER //#define STXXL_HAVE_MMAP_FILE 0/1 //#define STXXL_HAVE_SIMDISK_FILE 0/1 //#define STXXL_HAVE_BOOSTFD_FILE 0/1 //#define STXXL_HAVE_WINCALL_FILE 0/1 //#define STXXL_HAVE_WBTL_FILE 0/1 #define STXXL_HAVE_AIO_FILE 0 // only available on the kernelaio branch // default: 0/1 (platform and type dependent) // used in: io/*_file.h, io/*_file.cpp, mng/mng.cpp // affects: library // effect: enables/disables some file implementations //#define STXXL_CHECK_BLOCK_ALIGNING // default: not defined // used in: io/*_file.cpp // effect: call request::check_alignment() from request::request(...) //#define STXXL_CHECK_FOR_PENDING_REQUESTS_ON_SUBMISSION 0/1 // default: 1 // used in: io/*_queue*.cpp // affects: library // effect: check (and warn) for multiple concurrently pending I/O requests // for the same block, usually causing coherency problems on // out-of-order execution //#define STXXL_DO_NOT_COUNT_WAIT_TIME // default: not defined // used in: io/iostats.{h,cpp} // effect: makes calls to wait time counting functions no-ops //#define STXXL_WAIT_LOG_ENABLED // default: not defined // used in: common/log.cpp, io/iostats.cpp // effect: writes wait timing information to the file given via environment // variable STXXLWAITLOGFILE, does nothing if this is not defined //#define STXXL_PRINT_TIMESTAMP_ALWAYS // default: not defined // used in: common/verbose.cpp // affects: library // effect: prefix all MSG/ERRMSG/VERBOSE with elapsed time since program start //#define STXXL_SORT_OPTIMAL_PREFETCHING 0/1 // default: 1 // used in: algo/*sort.h, stream/sort_stream.h // effect if defined to 0: does not reorder prefetch requests to a disk // optimal schedule (Hutchinson, Sanders, Vitter: Duality between // prefetching and queued writing on parallel disks, 2005) //#define STXXL_CHECK_ORDER_IN_SORTS 0/1 // default: 0 // used in: algo/*sort.h, stream/sort_stream.h, containers/priority_queue.h // effect if set to 1: perform additional checking of sorted results //#define STXXL_NO_WARN_RECURSIVE_SORT // default: not defined // used in: algo/sort_base.h // affects: programs // effect if defined: does not print error messages about possibly inefficient // recursive merging //#define STXXL_HACK_SINGLE_IO_THREAD // default: not defined // used in: io/disk_queues.h // affects: programs // effect if defined: uses only a single I/O thread instead of one per disk // used e.g. by EcoSort which puts input file, output file and // scratch on a single disk (RAID0) #endif // !STXXL_DEFINES_HEADER stxxl-1.3.1/include/stxxl/bits/containers/0000755000175000017500000000000011536252421020426 5ustar andreasandreasstxxl-1.3.1/include/stxxl/bits/containers/btree/0000755000175000017500000000000011536252421021527 5ustar andreasandreasstxxl-1.3.1/include/stxxl/bits/containers/btree/iterator.h0000644000175000017500000002661111270157465023546 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/containers/btree/iterator.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2006 Roman Dementiev * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_CONTAINERS_BTREE__ITERATOR_H #define STXXL_CONTAINERS_BTREE__ITERATOR_H #include #include #include __STXXL_BEGIN_NAMESPACE namespace btree { template class iterator_map; template class btree_iterator; template class btree_const_iterator; template class normal_leaf; template class btree_iterator_base { public: typedef BTreeType btree_type; typedef typename btree_type::leaf_bid_type bid_type; typedef typename btree_type::value_type value_type; typedef typename btree_type::reference reference; typedef typename btree_type::const_reference const_reference; typedef std::bidirectional_iterator_tag iterator_category; typedef typename btree_type::difference_type difference_type; friend class iterator_map; template friend class normal_leaf; template friend bool operator == (const btree_iterator & a, const btree_const_iterator & b); template friend bool operator != (const btree_iterator & a, const btree_const_iterator & b); protected: btree_type * btree_; bid_type bid; unsigned pos; btree_iterator_base() { STXXL_VERBOSE3("btree_iterator_base def construct addr=" << this); make_invalid(); } btree_iterator_base( btree_type * btree__, const bid_type & b, unsigned p ) : btree_(btree__), bid(b), pos(p) { STXXL_VERBOSE3("btree_iterator_base parameter construct addr=" << this); btree_->iterator_map_.register_iterator(*this); } void make_invalid() { btree_ = NULL; } btree_iterator_base(const btree_iterator_base & obj) { STXXL_VERBOSE3("btree_iterator_base constr from" << (&obj) << " to " << this); btree_ = obj.btree_; bid = obj.bid; pos = obj.pos; if (btree_) btree_->iterator_map_.register_iterator(*this); } btree_iterator_base & operator = (const btree_iterator_base & obj) { STXXL_VERBOSE3("btree_iterator_base copy from" << (&obj) << " to " << this); if (&obj != this) { if (btree_) btree_->iterator_map_.unregister_iterator(*this); btree_ = obj.btree_; bid = obj.bid; pos = obj.pos; if (btree_) btree_->iterator_map_.register_iterator(*this); } return *this; } reference non_const_access() { assert(btree_); typename btree_type::leaf_type * Leaf = btree_->leaf_cache_.get_node(bid); assert(Leaf); return (reference)((*Leaf)[pos]); } const_reference const_access() const { assert(btree_); typename btree_type::leaf_type const * Leaf = btree_->leaf_cache_.get_const_node(bid); assert(Leaf); return (reference)((*Leaf)[pos]); } bool operator == (const btree_iterator_base & obj) const { return bid == obj.bid && pos == obj.pos && btree_ == obj.btree_; } bool operator != (const btree_iterator_base & obj) const { return bid != obj.bid || pos != obj.pos || btree_ != obj.btree_; } btree_iterator_base & increment() { assert(btree_); bid_type cur_bid = bid; typename btree_type::leaf_type const * Leaf = btree_->leaf_cache_.get_const_node(bid, true); assert(Leaf); Leaf->increment_iterator(*this); btree_->leaf_cache_.unfix_node(cur_bid); return *this; } btree_iterator_base & decrement() { assert(btree_); bid_type cur_bid = bid; typename btree_type::leaf_type const * Leaf = btree_->leaf_cache_.get_const_node(bid, true); assert(Leaf); Leaf->decrement_iterator(*this); btree_->leaf_cache_.unfix_node(cur_bid); return *this; } public: virtual ~btree_iterator_base() { STXXL_VERBOSE3("btree_iterator_base deconst " << this); if (btree_) btree_->iterator_map_.unregister_iterator(*this); } }; template class btree_iterator : public btree_iterator_base { public: typedef BTreeType btree_type; typedef typename btree_type::leaf_bid_type bid_type; typedef typename btree_type::value_type value_type; typedef typename btree_type::reference reference; typedef typename btree_type::const_reference const_reference; typedef typename btree_type::pointer pointer; template friend class normal_leaf; using btree_iterator_base::non_const_access; btree_iterator() : btree_iterator_base() { } btree_iterator(const btree_iterator & obj) : btree_iterator_base(obj) { } btree_iterator & operator = (const btree_iterator & obj) { btree_iterator_base::operator = (obj); return *this; } reference operator * () { return non_const_access(); } pointer operator -> () { return &(non_const_access()); } bool operator == (const btree_iterator & obj) const { return btree_iterator_base::operator == (obj); } bool operator != (const btree_iterator & obj) const { return btree_iterator_base::operator != (obj); } btree_iterator & operator ++ () { assert(*this != btree_iterator_base::btree_->end()); btree_iterator_base::increment(); return *this; } btree_iterator & operator -- () { btree_iterator_base::decrement(); return *this; } btree_iterator operator ++ (int) { assert(*this != btree_iterator_base::btree_->end()); btree_iterator result(*this); btree_iterator_base::increment(); return result; } btree_iterator operator -- (int) { btree_iterator result(*this); btree_iterator_base::decrement(); return result; } private: btree_iterator( btree_type * btree__, const bid_type & b, unsigned p ) : btree_iterator_base(btree__, b, p) { } }; template class btree_const_iterator : public btree_iterator_base { public: typedef btree_iterator iterator; typedef BTreeType btree_type; typedef typename btree_type::leaf_bid_type bid_type; typedef typename btree_type::value_type value_type; typedef typename btree_type::const_reference reference; typedef typename btree_type::const_pointer pointer; template friend class normal_leaf; using btree_iterator_base::const_access; btree_const_iterator() : btree_iterator_base() { } btree_const_iterator(const btree_const_iterator & obj) : btree_iterator_base(obj) { } btree_const_iterator(const iterator & obj) : btree_iterator_base(obj) { } btree_const_iterator & operator = (const btree_const_iterator & obj) { btree_iterator_base::operator = (obj); return *this; } reference operator * () { return const_access(); } pointer operator -> () { return &(const_access()); } bool operator == (const iterator & obj) const { return btree_iterator_base::operator == (obj); } bool operator != (const iterator & obj) const { return btree_iterator_base::operator != (obj); } bool operator == (const btree_const_iterator & obj) const { return btree_iterator_base::operator == (obj); } bool operator != (const btree_const_iterator & obj) const { return btree_iterator_base::operator != (obj); } btree_const_iterator & operator ++ () { assert(*this != btree_iterator_base::btree_->end()); btree_iterator_base::increment(); return *this; } btree_const_iterator & operator -- () { btree_iterator_base::decrement(); return *this; } btree_const_iterator operator ++ (int) { assert(*this != btree_iterator_base::btree_->end()); btree_const_iterator result(*this); btree_iterator_base::increment(); return result; } btree_const_iterator operator -- (int) { btree_const_iterator result(*this); btree_iterator_base::decrement(); return result; } private: btree_const_iterator( btree_type * btree__, const bid_type & b, unsigned p ) : btree_iterator_base(btree__, b, p) { } }; template inline bool operator == (const btree_iterator & a, const btree_const_iterator & b) { return a.btree_iterator_base::operator == (b); } template inline bool operator != (const btree_iterator & a, const btree_const_iterator & b) { return a.btree_iterator_base::operator != (b); } } __STXXL_END_NAMESPACE #endif /* STXXL_CONTAINERS_BTREE__ITERATOR_H */ stxxl-1.3.1/include/stxxl/bits/containers/btree/btree.h0000644000175000017500000012726311531237734023021 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/containers/btree/btree.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2006, 2008 Roman Dementiev * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_CONTAINERS_BTREE__BTREE_H #define STXXL_CONTAINERS_BTREE__BTREE_H #include #include #include #include #include #include #include #include #include __STXXL_BEGIN_NAMESPACE namespace btree { template class btree : private noncopyable { public: typedef KeyType key_type; typedef DataType data_type; typedef CompareType key_compare; typedef btree SelfType; typedef PDAllocStrategy alloc_strategy_type; typedef stxxl::uint64 size_type; typedef stxxl::int64 difference_type; typedef std::pair value_type; typedef value_type & reference; typedef const value_type & const_reference; typedef value_type * pointer; typedef value_type const * const_pointer; // leaf type declarations typedef normal_leaf leaf_type; friend class normal_leaf; typedef typename leaf_type::block_type leaf_block_type; typedef typename leaf_type::bid_type leaf_bid_type; typedef node_cache leaf_cache_type; friend class node_cache; // iterator types typedef btree_iterator iterator; typedef btree_const_iterator const_iterator; friend class btree_iterator_base; // iterator map type typedef iterator_map iterator_map_type; // node type declarations typedef normal_node node_type; typedef typename node_type::block_type node_block_type; friend class normal_node; typedef typename node_type::bid_type node_bid_type; typedef node_cache node_cache_type; friend class node_cache; typedef typename leaf_type::value_compare value_compare; enum { min_node_size = node_type::min_size, max_node_size = node_type::max_size, min_leaf_size = leaf_type::min_size, max_leaf_size = leaf_type::max_size }; private: key_compare key_compare_; mutable node_cache_type node_cache_; mutable leaf_cache_type leaf_cache_; iterator_map_type iterator_map_; size_type size_; unsigned_type height_; bool prefetching_enabled_; block_manager * bm_; alloc_strategy_type alloc_strategy_; typedef std::map root_node_type; typedef typename root_node_type::iterator root_node_iterator_type; typedef typename root_node_type::const_iterator root_node_const_iterator_type; typedef std::pair root_node_pair_type; root_node_type root_node_; iterator end_iterator; template void insert_into_root(const std::pair & splitter) { std::pair result = root_node_.insert(splitter); assert(result.second == true); if (root_node_.size() > max_node_size) // root overflow { STXXL_VERBOSE1("btree::insert_into_root, overflow happened, splitting"); node_bid_type LeftBid; node_type * LeftNode = node_cache_.get_new_node(LeftBid); assert(LeftNode); node_bid_type RightBid; node_type * RightNode = node_cache_.get_new_node(RightBid); assert(RightNode); const unsigned_type old_size = root_node_.size(); const unsigned_type half = root_node_.size() / 2; unsigned_type i = 0; root_node_iterator_type it = root_node_.begin(); typename node_block_type::iterator block_it = LeftNode->block().begin(); while (i < half) // copy smaller part { *block_it = *it; ++i; ++block_it; ++it; } LeftNode->block().info.cur_size = half; key_type LeftKey = (LeftNode->block()[half - 1]).first; block_it = RightNode->block().begin(); while (i < old_size) // copy larger part { *block_it = *it; ++i; ++block_it; ++it; } unsigned_type right_size = RightNode->block().info.cur_size = old_size - half; key_type RightKey = (RightNode->block()[right_size - 1]).first; assert(old_size == RightNode->size() + LeftNode->size()); // create new root node root_node_.clear(); root_node_.insert(root_node_pair_type(LeftKey, LeftBid)); root_node_.insert(root_node_pair_type(RightKey, RightBid)); ++height_; STXXL_VERBOSE1("btree Increasing height to " << height_); if (node_cache_.size() < (height_ - 1)) { STXXL_THROW(std::runtime_error, "btree::bulk_construction", "The height of the tree (" << height_ << ") has exceeded the required capacity (" << (node_cache_.size() + 1) << ") of the node cache. " << "Increase the node cache size."); } } } template void fuse_or_balance(root_node_iterator_type UIt, CacheType & cache_) { typedef typename CacheType::node_type local_node_type; typedef typename local_node_type::bid_type local_bid_type; root_node_iterator_type leftIt, rightIt; if (UIt->first == key_compare::max_value()) // UIt is the last entry in the root { assert(UIt != root_node_.begin()); rightIt = UIt; leftIt = --UIt; } else { leftIt = UIt; rightIt = ++UIt; assert(rightIt != root_node_.end()); } // now fuse or balance nodes pointed by leftIt and rightIt local_bid_type LeftBid = (local_bid_type)leftIt->second; local_bid_type RightBid = (local_bid_type)rightIt->second; local_node_type * LeftNode = cache_.get_node(LeftBid, true); local_node_type * RightNode = cache_.get_node(RightBid, true); const unsigned_type TotalSize = LeftNode->size() + RightNode->size(); if (TotalSize <= RightNode->max_nelements()) { // fuse RightNode->fuse(*LeftNode); // add the content of LeftNode to RightNode cache_.unfix_node(RightBid); cache_.delete_node(LeftBid); // 'delete_node' unfixes LeftBid also root_node_.erase(leftIt); // delete left BID from the root } else { // balance key_type NewSplitter = RightNode->balance(*LeftNode); root_node_.erase(leftIt); // delete left BID from the root // reinsert with the new key root_node_.insert(root_node_pair_type(NewSplitter, (node_bid_type)LeftBid)); cache_.unfix_node(LeftBid); cache_.unfix_node(RightBid); } } void create_empty_leaf() { leaf_bid_type NewBid; leaf_type * NewLeaf = leaf_cache_.get_new_node(NewBid); assert(NewLeaf); end_iterator = NewLeaf->end(); // initialize end() iterator root_node_.insert(root_node_pair_type(key_compare::max_value(), (node_bid_type)NewBid)); } void deallocate_children() { if (height_ == 2) { // we have children leaves here root_node_const_iterator_type it = root_node_.begin(); for ( ; it != root_node_.end(); ++it) { // delete from leaf cache and deallocate bid leaf_cache_.delete_node((leaf_bid_type)it->second); } } else { root_node_const_iterator_type it = root_node_.begin(); for ( ; it != root_node_.end(); ++it) { node_type * Node = node_cache_.get_node((node_bid_type)it->second); assert(Node); Node->deallocate_children(height_ - 1); // delete from node cache and deallocate bid node_cache_.delete_node((node_bid_type)it->second); } } } template void bulk_construction(InputIterator b, InputIterator e, double node_fill_factor, double leaf_fill_factor) { assert(node_fill_factor >= 0.5); assert(leaf_fill_factor >= 0.5); key_type lastKey = key_compare::max_value(); typedef std::pair key_bid_pair; typedef typename stxxl::VECTOR_GENERATOR::result key_bid_vector_type; key_bid_vector_type Bids; leaf_bid_type NewBid; leaf_type * Leaf = leaf_cache_.get_new_node(NewBid); const unsigned_type max_leaf_elements = unsigned_type(double(Leaf->max_nelements()) * leaf_fill_factor); while (b != e) { // write data in leaves // if *b not equal to the last element if (key_compare_(b->first, lastKey) || key_compare_(lastKey, b->first)) { ++size_; if (Leaf->size() == max_leaf_elements) { // overflow, need a new block Bids.push_back(key_bid_pair(Leaf->back().first, (node_bid_type)NewBid)); leaf_type * NewLeaf = leaf_cache_.get_new_node(NewBid); assert(NewLeaf); // Setting links Leaf->succ() = NewLeaf->my_bid(); NewLeaf->pred() = Leaf->my_bid(); Leaf = NewLeaf; } Leaf->push_back(*b); lastKey = b->first; } ++b; } // rebalance the last leaf if (Leaf->underflows() && !Bids.empty()) { leaf_type * LeftLeaf = leaf_cache_.get_node((leaf_bid_type)(Bids.back().second)); assert(LeftLeaf); if (LeftLeaf->size() + Leaf->size() <= Leaf->max_nelements()) // can fuse { Leaf->fuse(*LeftLeaf); leaf_cache_.delete_node((leaf_bid_type)(Bids.back().second)); Bids.pop_back(); assert(!Leaf->overflows() && !Leaf->underflows()); } else { // need to rebalance const key_type NewSplitter = Leaf->balance(*LeftLeaf); Bids.back().first = NewSplitter; assert(!LeftLeaf->overflows() && !LeftLeaf->underflows()); } } assert(!Leaf->overflows() && (!Leaf->underflows() || size_ <= max_leaf_size)); end_iterator = Leaf->end(); // initialize end() iterator Bids.push_back(key_bid_pair(key_compare::max_value(), (node_bid_type)NewBid)); const unsigned_type max_node_elements = unsigned_type(double(max_node_size) * node_fill_factor); while (Bids.size() > max_node_elements) { key_bid_vector_type ParentBids; stxxl::uint64 nparents = div_ceil(Bids.size(), max_node_elements); assert(nparents >= 2); STXXL_VERBOSE1("btree bulk constructBids.size() " << Bids.size() << " nparents: " << nparents << " max_ns: " << max_node_elements); typename key_bid_vector_type::const_iterator it = Bids.begin(); do { node_bid_type NewBid; node_type * Node = node_cache_.get_new_node(NewBid); assert(Node); unsigned_type cnt = 0; for ( ; cnt < max_node_elements && it != Bids.end(); ++cnt, ++it) { Node->push_back(*it); } STXXL_VERBOSE1("btree bulk construct Node size : " << Node->size() << " limits: " << Node->min_nelements() << " " << Node->max_nelements() << " max_node_elements: " << max_node_elements); if (Node->underflows()) { assert(it == Bids.end()); // this can happen only at the end assert(!ParentBids.empty()); node_type * LeftNode = node_cache_.get_node(ParentBids.back().second); assert(LeftNode); if (LeftNode->size() + Node->size() <= Node->max_nelements()) // can fuse { Node->fuse(*LeftNode); node_cache_.delete_node(ParentBids.back().second); ParentBids.pop_back(); } else { // need to rebalance const key_type NewSplitter = Node->balance(*LeftNode); ParentBids.back().first = NewSplitter; assert(!LeftNode->overflows() && !LeftNode->underflows()); } } assert(!Node->overflows() && !Node->underflows()); ParentBids.push_back(key_bid_pair(Node->back().first, NewBid)); } while (it != Bids.end()); std::swap(ParentBids, Bids); assert(nparents == Bids.size() || (nparents - 1) == Bids.size()); ++height_; STXXL_VERBOSE1("Increasing height to " << height_); if (node_cache_.size() < (height_ - 1)) { STXXL_THROW(std::runtime_error, "btree::bulk_construction", "The height of the tree (" << height_ << ") has exceeded the required capacity (" << (node_cache_.size() + 1) << ") of the node cache. " << "Increase the node cache size."); } } root_node_.insert(Bids.begin(), Bids.end()); } public: btree(unsigned_type node_cache_size_in_bytes, unsigned_type leaf_cache_size_in_bytes ) : node_cache_(node_cache_size_in_bytes, this, key_compare_), leaf_cache_(leaf_cache_size_in_bytes, this, key_compare_), iterator_map_(this), size_(0), height_(2), prefetching_enabled_(true), bm_(block_manager::get_instance()) { STXXL_VERBOSE1("Creating a btree, addr=" << this); STXXL_VERBOSE1(" bytes in a node: " << node_bid_type::size); STXXL_VERBOSE1(" bytes in a leaf: " << leaf_bid_type::size); STXXL_VERBOSE1(" elements in a node: " << node_block_type::size); STXXL_VERBOSE1(" elements in a leaf: " << leaf_block_type::size); STXXL_VERBOSE1(" size of a node element: " << sizeof(typename node_block_type::value_type)); STXXL_VERBOSE1(" size of a leaf element: " << sizeof(typename leaf_block_type::value_type)); create_empty_leaf(); } btree(const key_compare & c_, unsigned_type node_cache_size_in_bytes, unsigned_type leaf_cache_size_in_bytes ) : key_compare_(c_), node_cache_(node_cache_size_in_bytes, this, key_compare_), leaf_cache_(leaf_cache_size_in_bytes, this, key_compare_), iterator_map_(this), size_(0), height_(2), prefetching_enabled_(true), bm_(block_manager::get_instance()) { STXXL_VERBOSE1("Creating a btree, addr=" << this); STXXL_VERBOSE1(" bytes in a node: " << node_bid_type::size); STXXL_VERBOSE1(" bytes in a leaf: " << leaf_bid_type::size); create_empty_leaf(); } virtual ~btree() { try { deallocate_children(); } catch (...) { // no exceptions in destructor } } size_type size() const { return size_; } size_type max_size() const { return (std::numeric_limits::max)(); } bool empty() const { return !size_; } std::pair insert(const value_type & x) { root_node_iterator_type it = root_node_.lower_bound(x.first); assert(!root_node_.empty()); assert(it != root_node_.end()); if (height_ == 2) // 'it' points to a leaf { STXXL_VERBOSE1("Inserting new value into a leaf"); leaf_type * Leaf = leaf_cache_.get_node((leaf_bid_type)it->second, true); assert(Leaf); std::pair Splitter; std::pair result = Leaf->insert(x, Splitter); if (result.second) ++size_; leaf_cache_.unfix_node((leaf_bid_type)it->second); //if(key_compare::max_value() == Splitter.first) if (!(key_compare_(key_compare::max_value(), Splitter.first) || key_compare_(Splitter.first, key_compare::max_value()))) return result; // no overflow/splitting happened STXXL_VERBOSE1("Inserting new value into root node"); insert_into_root(Splitter); assert(leaf_cache_.nfixed() == 0); assert(node_cache_.nfixed() == 0); return result; } // 'it' points to a node STXXL_VERBOSE1("Inserting new value into a node"); node_type * Node = node_cache_.get_node((node_bid_type)it->second, true); assert(Node); std::pair Splitter; std::pair result = Node->insert(x, height_ - 1, Splitter); if (result.second) ++size_; node_cache_.unfix_node((node_bid_type)it->second); //if(key_compare::max_value() == Splitter.first) if (!(key_compare_(key_compare::max_value(), Splitter.first) || key_compare_(Splitter.first, key_compare::max_value()))) return result; // no overflow/splitting happened STXXL_VERBOSE1("Inserting new value into root node"); insert_into_root(Splitter); assert(leaf_cache_.nfixed() == 0); assert(node_cache_.nfixed() == 0); return result; } iterator begin() { root_node_iterator_type it = root_node_.begin(); assert(it != root_node_.end()); if (height_ == 2) // 'it' points to a leaf { STXXL_VERBOSE1("btree: retrieving begin() from the first leaf"); leaf_type * Leaf = leaf_cache_.get_node((leaf_bid_type)it->second); assert(Leaf); assert(leaf_cache_.nfixed() == 0); assert(node_cache_.nfixed() == 0); return Leaf->begin(); } // 'it' points to a node STXXL_VERBOSE1("btree: retrieving begin() from the first node"); node_type * Node = node_cache_.get_node((node_bid_type)it->second, true); assert(Node); iterator result = Node->begin(height_ - 1); node_cache_.unfix_node((node_bid_type)it->second); assert(leaf_cache_.nfixed() == 0); assert(node_cache_.nfixed() == 0); return result; } const_iterator begin() const { root_node_const_iterator_type it = root_node_.begin(); assert(it != root_node_.end()); if (height_ == 2) // 'it' points to a leaf { STXXL_VERBOSE1("btree: retrieving begin() from the first leaf"); leaf_type const * Leaf = leaf_cache_.get_const_node((leaf_bid_type)it->second); assert(Leaf); assert(leaf_cache_.nfixed() == 0); assert(node_cache_.nfixed() == 0); return Leaf->begin(); } // 'it' points to a node STXXL_VERBOSE1("btree: retrieving begin() from the first node"); node_type const * Node = node_cache_.get_const_node((node_bid_type)it->second, true); assert(Node); const_iterator result = Node->begin(height_ - 1); node_cache_.unfix_node((node_bid_type)it->second); assert(leaf_cache_.nfixed() == 0); assert(node_cache_.nfixed() == 0); return result; } iterator end() { return end_iterator; } const_iterator end() const { return end_iterator; } data_type & operator [] (const key_type & k) { return (*((insert(value_type(k, data_type()))).first)).second; } iterator find(const key_type & k) { root_node_iterator_type it = root_node_.lower_bound(k); assert(it != root_node_.end()); if (height_ == 2) // 'it' points to a leaf { STXXL_VERBOSE1("Searching in a leaf"); leaf_type * Leaf = leaf_cache_.get_node((leaf_bid_type)it->second, true); assert(Leaf); iterator result = Leaf->find(k); leaf_cache_.unfix_node((leaf_bid_type)it->second); assert(result == end() || result->first == k); assert(leaf_cache_.nfixed() == 0); assert(node_cache_.nfixed() == 0); return result; } // 'it' points to a node STXXL_VERBOSE1("Searching in a node"); node_type * Node = node_cache_.get_node((node_bid_type)it->second, true); assert(Node); iterator result = Node->find(k, height_ - 1); node_cache_.unfix_node((node_bid_type)it->second); assert(result == end() || result->first == k); assert(leaf_cache_.nfixed() == 0); assert(node_cache_.nfixed() == 0); return result; } const_iterator find(const key_type & k) const { root_node_const_iterator_type it = root_node_.lower_bound(k); assert(it != root_node_.end()); if (height_ == 2) // 'it' points to a leaf { STXXL_VERBOSE1("Searching in a leaf"); leaf_type const * Leaf = leaf_cache_.get_const_node((leaf_bid_type)it->second, true); assert(Leaf); const_iterator result = Leaf->find(k); leaf_cache_.unfix_node((leaf_bid_type)it->second); assert(result == end() || result->first == k); assert(leaf_cache_.nfixed() == 0); assert(node_cache_.nfixed() == 0); return result; } // 'it' points to a node STXXL_VERBOSE1("Searching in a node"); node_type const * Node = node_cache_.get_const_node((node_bid_type)it->second, true); assert(Node); const_iterator result = Node->find(k, height_ - 1); node_cache_.unfix_node((node_bid_type)it->second); assert(result == end() || result->first == k); assert(leaf_cache_.nfixed() == 0); assert(node_cache_.nfixed() == 0); return result; } iterator lower_bound(const key_type & k) { root_node_iterator_type it = root_node_.lower_bound(k); assert(it != root_node_.end()); if (height_ == 2) // 'it' points to a leaf { STXXL_VERBOSE1("Searching lower bound in a leaf"); leaf_type * Leaf = leaf_cache_.get_node((leaf_bid_type)it->second, true); assert(Leaf); iterator result = Leaf->lower_bound(k); leaf_cache_.unfix_node((leaf_bid_type)it->second); assert(leaf_cache_.nfixed() == 0); assert(node_cache_.nfixed() == 0); return result; } // 'it' points to a node STXXL_VERBOSE1("Searching lower bound in a node"); node_type * Node = node_cache_.get_node((node_bid_type)it->second, true); assert(Node); iterator result = Node->lower_bound(k, height_ - 1); node_cache_.unfix_node((node_bid_type)it->second); assert(leaf_cache_.nfixed() == 0); assert(node_cache_.nfixed() == 0); return result; } const_iterator lower_bound(const key_type & k) const { root_node_const_iterator_type it = root_node_.lower_bound(k); assert(it != root_node_.end()); if (height_ == 2) // 'it' points to a leaf { STXXL_VERBOSE1("Searching lower bound in a leaf"); leaf_type const * Leaf = leaf_cache_.get_const_node((leaf_bid_type)it->second, true); assert(Leaf); const_iterator result = Leaf->lower_bound(k); leaf_cache_.unfix_node((leaf_bid_type)it->second); assert(leaf_cache_.nfixed() == 0); assert(node_cache_.nfixed() == 0); return result; } // 'it' points to a node STXXL_VERBOSE1("Searching lower bound in a node"); node_type const * Node = node_cache_.get_const_node((node_bid_type)it->second, true); assert(Node); const_iterator result = Node->lower_bound(k, height_ - 1); node_cache_.unfix_node((node_bid_type)it->second); assert(leaf_cache_.nfixed() == 0); assert(node_cache_.nfixed() == 0); return result; } iterator upper_bound(const key_type & k) { root_node_iterator_type it = root_node_.upper_bound(k); assert(it != root_node_.end()); if (height_ == 2) // 'it' points to a leaf { STXXL_VERBOSE1("Searching upper bound in a leaf"); leaf_type * Leaf = leaf_cache_.get_node((leaf_bid_type)it->second, true); assert(Leaf); iterator result = Leaf->upper_bound(k); leaf_cache_.unfix_node((leaf_bid_type)it->second); assert(leaf_cache_.nfixed() == 0); assert(node_cache_.nfixed() == 0); return result; } // 'it' points to a node STXXL_VERBOSE1("Searching upper bound in a node"); node_type * Node = node_cache_.get_node((node_bid_type)it->second, true); assert(Node); iterator result = Node->upper_bound(k, height_ - 1); node_cache_.unfix_node((node_bid_type)it->second); assert(leaf_cache_.nfixed() == 0); assert(node_cache_.nfixed() == 0); return result; } const_iterator upper_bound(const key_type & k) const { root_node_const_iterator_type it = root_node_.upper_bound(k); assert(it != root_node_.end()); if (height_ == 2) // 'it' points to a leaf { STXXL_VERBOSE1("Searching upper bound in a leaf"); leaf_type const * Leaf = leaf_cache_.get_const_node((leaf_bid_type)it->second, true); assert(Leaf); const_iterator result = Leaf->upper_bound(k); leaf_cache_.unfix_node((leaf_bid_type)it->second); assert(leaf_cache_.nfixed() == 0); assert(node_cache_.nfixed() == 0); return result; } // 'it' points to a node STXXL_VERBOSE1("Searching upper bound in a node"); node_type const * Node = node_cache_.get_const_node((node_bid_type)it->second, true); assert(Node); const_iterator result = Node->upper_bound(k, height_ - 1); node_cache_.unfix_node((node_bid_type)it->second); assert(leaf_cache_.nfixed() == 0); assert(node_cache_.nfixed() == 0); return result; } std::pair equal_range(const key_type & k) { iterator l = lower_bound(k); // l->first >= k if (l == end() || key_compare_(k, l->first)) // if (k < l->first) return std::pair(l, l); // then upper_bound == lower_bound iterator u = l; ++u; // only one element ==k can exist assert(leaf_cache_.nfixed() == 0); assert(node_cache_.nfixed() == 0); return std::pair(l, u); // then upper_bound == (lower_bound+1) } std::pair equal_range(const key_type & k) const { const_iterator l = lower_bound(k); // l->first >= k if (l == end() || key_compare_(k, l->first)) // if (k < l->first) return std::pair(l, l); // then upper_bound == lower_bound const_iterator u = l; ++u; // only one element ==k can exist assert(leaf_cache_.nfixed() == 0); assert(node_cache_.nfixed() == 0); return std::pair(l, u); // then upper_bound == (lower_bound+1) } size_type erase(const key_type & k) { root_node_iterator_type it = root_node_.lower_bound(k); assert(it != root_node_.end()); if (height_ == 2) // 'it' points to a leaf { STXXL_VERBOSE1("Deleting key from a leaf"); leaf_type * Leaf = leaf_cache_.get_node((leaf_bid_type)it->second, true); assert(Leaf); size_type result = Leaf->erase(k); size_ -= result; leaf_cache_.unfix_node((leaf_bid_type)it->second); assert(leaf_cache_.nfixed() == 0); assert(node_cache_.nfixed() == 0); if ((!Leaf->underflows()) || root_node_.size() == 1) return result; // no underflow or root has a special degree 1 (too few elements) STXXL_VERBOSE1("btree: Fusing or rebalancing a leaf"); fuse_or_balance(it, leaf_cache_); assert(leaf_cache_.nfixed() == 0); assert(node_cache_.nfixed() == 0); return result; } // 'it' points to a node STXXL_VERBOSE1("Deleting key from a node"); assert(root_node_.size() >= 2); node_type * Node = node_cache_.get_node((node_bid_type)it->second, true); assert(Node); size_type result = Node->erase(k, height_ - 1); size_ -= result; node_cache_.unfix_node((node_bid_type)it->second); assert(leaf_cache_.nfixed() == 0); assert(node_cache_.nfixed() == 0); if (!Node->underflows()) return result; // no underflow happened STXXL_VERBOSE1("Fusing or rebalancing a node"); fuse_or_balance(it, node_cache_); if (root_node_.size() == 1) { STXXL_VERBOSE1("btree Root has size 1 and height > 2"); STXXL_VERBOSE1("btree Deallocate root and decrease height"); it = root_node_.begin(); node_bid_type RootBid = it->second; assert(it->first == key_compare::max_value()); node_type * RootNode = node_cache_.get_node(RootBid); assert(RootNode); assert(RootNode->back().first == key_compare::max_value()); root_node_.clear(); root_node_.insert(RootNode->block().begin(), RootNode->block().begin() + RootNode->size()); node_cache_.delete_node(RootBid); --height_; STXXL_VERBOSE1("btree Decreasing height to " << height_); } assert(leaf_cache_.nfixed() == 0); assert(node_cache_.nfixed() == 0); return result; } size_type count(const key_type & k) { if (find(k) == end()) return 0; return 1; } void erase(iterator pos) { assert(pos != end()); #ifndef NDEBUG size_type old_size = size(); #endif erase(pos->first); assert(size() == old_size - 1); } iterator insert(iterator /*pos*/, const value_type & x) { return insert(x).first; // pos ignored in the current version } void clear() { deallocate_children(); root_node_.clear(); size_ = 0; height_ = 2, create_empty_leaf(); assert(leaf_cache_.nfixed() == 0); assert(node_cache_.nfixed() == 0); } template void insert(InputIterator b, InputIterator e) { while (b != e) { insert(*(b++)); } } template btree(InputIterator b, InputIterator e, const key_compare & c_, unsigned_type node_cache_size_in_bytes, unsigned_type leaf_cache_size_in_bytes, bool range_sorted = false, double node_fill_factor = 0.75, double leaf_fill_factor = 0.6 ) : key_compare_(c_), node_cache_(node_cache_size_in_bytes, this, key_compare_), leaf_cache_(leaf_cache_size_in_bytes, this, key_compare_), iterator_map_(this), size_(0), height_(2), prefetching_enabled_(true), bm_(block_manager::get_instance()) { STXXL_VERBOSE1("Creating a btree, addr=" << this); STXXL_VERBOSE1(" bytes in a node: " << node_bid_type::size); STXXL_VERBOSE1(" bytes in a leaf: " << leaf_bid_type::size); if (range_sorted == false) { create_empty_leaf(); insert(b, e); assert(leaf_cache_.nfixed() == 0); assert(node_cache_.nfixed() == 0); return; } bulk_construction(b, e, node_fill_factor, leaf_fill_factor); assert(leaf_cache_.nfixed() == 0); assert(node_cache_.nfixed() == 0); } template btree(InputIterator b, InputIterator e, unsigned_type node_cache_size_in_bytes, unsigned_type leaf_cache_size_in_bytes, bool range_sorted = false, double node_fill_factor = 0.75, double leaf_fill_factor = 0.6 ) : node_cache_(node_cache_size_in_bytes, this, key_compare_), leaf_cache_(leaf_cache_size_in_bytes, this, key_compare_), iterator_map_(this), size_(0), height_(2), prefetching_enabled_(true), bm_(block_manager::get_instance()) { STXXL_VERBOSE1("Creating a btree, addr=" << this); STXXL_VERBOSE1(" bytes in a node: " << node_bid_type::size); STXXL_VERBOSE1(" bytes in a leaf: " << leaf_bid_type::size); if (range_sorted == false) { create_empty_leaf(); insert(b, e); assert(leaf_cache_.nfixed() == 0); assert(node_cache_.nfixed() == 0); return; } bulk_construction(b, e, node_fill_factor, leaf_fill_factor); assert(leaf_cache_.nfixed() == 0); assert(node_cache_.nfixed() == 0); } void erase(iterator first, iterator last) { if (first == begin() && last == end()) clear(); else while (first != last) erase(first++); } key_compare key_comp() const { return key_compare_; } value_compare value_comp() const { return value_compare(key_compare_); } void swap(btree & obj) { std::swap(key_compare_, obj.key_compare_); // OK std::swap(node_cache_, obj.node_cache_); // OK std::swap(leaf_cache_, obj.leaf_cache_); // OK std::swap(iterator_map_, obj.iterator_map_); // must update all iterators std::swap(end_iterator, obj.end_iterator); std::swap(size_, obj.size_); std::swap(height_, obj.height_); std::swap(alloc_strategy_, obj.alloc_strategy_); std::swap(root_node_, obj.root_node_); } void enable_prefetching() { prefetching_enabled_ = true; } void disable_prefetching() { prefetching_enabled_ = false; } bool prefetching_enabled() { return prefetching_enabled_; } void print_statistics(std::ostream & o) const { o << "Node cache statistics:" << std::endl; node_cache_.print_statistics(o); o << "Leaf cache statistics:" << std::endl; leaf_cache_.print_statistics(o); } void reset_statistics() { node_cache_.reset_statistics(); leaf_cache_.reset_statistics(); } }; template inline bool operator == (const btree & a, const btree & b) { return a.size() == b.size() && std::equal(a.begin(), a.end(), b.begin()); } template inline bool operator != (const btree & a, const btree & b) { return !(a == b); } template inline bool operator < (const btree & a, const btree & b) { return std::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end()); } template inline bool operator > (const btree & a, const btree & b) { return b < a; } template inline bool operator <= (const btree & a, const btree & b) { return !(b < a); } template inline bool operator >= (const btree & a, const btree & b) { return !(a < b); } } __STXXL_END_NAMESPACE namespace std { template void swap(stxxl::btree::btree & a, stxxl::btree::btree & b) { if (&a != &b) a.swap(b); } } #endif /* STXXL_CONTAINERS_BTREE__BTREE_H */ stxxl-1.3.1/include/stxxl/bits/containers/btree/node.h0000644000175000017500000006677511420040354022642 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/containers/btree/node.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2006 Roman Dementiev * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_CONTAINERS_BTREE__NODE_H #define STXXL_CONTAINERS_BTREE__NODE_H #include #include __STXXL_BEGIN_NAMESPACE namespace btree { template class node_cache; template class normal_node : private noncopyable { public: typedef normal_node SelfType; friend class node_cache; typedef KeyType_ key_type; typedef KeyCmp_ key_compare; enum { raw_size = RawSize_ }; typedef BID bid_type; typedef bid_type node_bid_type; typedef SelfType node_type; typedef std::pair value_type; typedef value_type & reference; typedef const value_type & const_reference; struct InfoType { bid_type me; unsigned cur_size; }; typedef typed_block block_type; enum { nelements = block_type::size - 1, max_size = nelements, min_size = nelements / 2 }; typedef typename block_type::iterator block_iterator; typedef typename block_type::const_iterator block_const_iterator; typedef BTreeType btree_type; typedef typename btree_type::size_type size_type; typedef typename btree_type::iterator iterator; typedef typename btree_type::const_iterator const_iterator; typedef typename btree_type::value_type btree_value_type; typedef typename btree_type::leaf_bid_type leaf_bid_type; typedef typename btree_type::leaf_type leaf_type; typedef node_cache node_cache_type; private: struct value_compare : public std::binary_function { key_compare comp; value_compare(key_compare c) : comp(c) { } bool operator () (const value_type & x, const value_type & y) const { return comp(x.first, y.first); } }; block_type * block_; btree_type * btree_; key_compare cmp_; value_compare vcmp_; template std::pair insert(const std::pair & splitter, const block_iterator & place2insert) { std::pair result(key_compare::max_value(), bid_type()); // splitter != *place2insert assert(vcmp_(*place2insert, splitter) || vcmp_(splitter, *place2insert)); block_iterator cur = block_->begin() + size() - 1; for ( ; cur >= place2insert; --cur) *(cur + 1) = *cur; // copy elements to make space for the new element *place2insert = splitter; // insert ++(block_->info.cur_size); if (size() > max_nelements()) // overflow! need to split { STXXL_VERBOSE1("btree::normal_node::insert overflow happened, splitting"); bid_type NewBid; btree_->node_cache_.get_new_node(NewBid); // new (left) node normal_node * NewNode = btree_->node_cache_.get_node(NewBid, true); assert(NewNode); const unsigned end_of_smaller_part = size() / 2; result.first = ((*block_)[end_of_smaller_part - 1]).first; result.second = NewBid; const unsigned old_size = size(); // copy the smaller part std::copy(block_->begin(), block_->begin() + end_of_smaller_part, NewNode->block_->begin()); NewNode->block_->info.cur_size = end_of_smaller_part; // copy the larger part std::copy(block_->begin() + end_of_smaller_part, block_->begin() + old_size, block_->begin()); block_->info.cur_size = old_size - end_of_smaller_part; assert(size() + NewNode->size() == old_size); btree_->node_cache_.unfix_node(NewBid); STXXL_VERBOSE1("btree::normal_node split leaf " << this << " splitter: " << result.first); } return result; } template void fuse_or_balance(block_iterator UIt, CacheType & cache_) { typedef typename CacheType::node_type local_node_type; typedef typename local_node_type::bid_type local_bid_type; block_iterator leftIt, rightIt; if (UIt == (block_->begin() + size() - 1)) // UIt is the last entry in the root { assert(UIt != block_->begin()); rightIt = UIt; leftIt = --UIt; } else { leftIt = UIt; rightIt = ++UIt; assert(rightIt != (block_->begin() + size())); } // now fuse or balance nodes pointed by leftIt and rightIt local_bid_type LeftBid = (local_bid_type)leftIt->second; local_bid_type RightBid = (local_bid_type)rightIt->second; local_node_type * LeftNode = cache_.get_node(LeftBid, true); local_node_type * RightNode = cache_.get_node(RightBid, true); const unsigned TotalSize = LeftNode->size() + RightNode->size(); if (TotalSize <= RightNode->max_nelements()) { // fuse RightNode->fuse(*LeftNode); // add the content of LeftNode to RightNode cache_.unfix_node(RightBid); cache_.delete_node(LeftBid); // 'delete_node' unfixes LeftBid also std::copy(leftIt + 1, block_->begin() + size(), leftIt); // delete left BID from the root --(block_->info.cur_size); } else { // balance key_type NewSplitter = RightNode->balance(*LeftNode); leftIt->first = NewSplitter; // change key assert(vcmp_(*leftIt, *rightIt)); cache_.unfix_node(LeftBid); cache_.unfix_node(RightBid); } } public: virtual ~normal_node() { delete block_; } normal_node(btree_type * btree__, key_compare cmp) : block_(new block_type), btree_(btree__), cmp_(cmp), vcmp_(cmp) { assert(min_nelements() >= 2); assert(2 * min_nelements() - 1 <= max_nelements()); assert(max_nelements() <= nelements); assert(unsigned(block_type::size) >= nelements + 1); // extra space for an overflow } block_type & block() { return *block_; } bool overflows() const { return block_->info.cur_size > max_nelements(); } bool underflows() const { return block_->info.cur_size < min_nelements(); } unsigned max_nelements() const { return max_size; } unsigned min_nelements() const { return min_size; } /* template normal_node(InputIterator begin_, InputIterator end_, btree_type * btree__, key_compare cmp): block_(new block_type), btree_(btree__), cmp_(cmp), vcmp_(cmp) { assert(min_nelements() >=2); assert(2*min_nelements() - 1 <= max_nelements()); assert(max_nelements() <= nelements); assert(unsigned(block_type::size) >= nelements +1); // extra space for an overflow unsigned new_size = end_ - begin_; assert(new_size <= max_nelements()); assert(new_size >= min_nelements()); std::copy(begin_,end_,block_->begin()); assert(stxxl::is_sorted(block_->begin(),block_->begin() + new_size, vcmp_)); block_->info.cur_size = new_size; }*/ unsigned size() const { return block_->info.cur_size; } bid_type my_bid() const { return block_->info.me; } void save() { request_ptr req = block_->write(my_bid()); req->wait(); } request_ptr load(const bid_type & bid) { request_ptr req = block_->read(bid); req->wait(); assert(bid == my_bid()); return req; } request_ptr prefetch(const bid_type & bid) { return block_->read(bid); } void init(const bid_type & my_bid_) { block_->info.me = my_bid_; block_->info.cur_size = 0; } reference operator [] (int i) { return (*block_)[i]; } const_reference operator [] (int i) const { return (*block_)[i]; } reference back() { return (*block_)[size() - 1]; } reference front() { return *(block_->begin()); } const_reference back() const { return (*block_)[size() - 1]; } const_reference front() const { return *(block_->begin()); } std::pair insert( const btree_value_type & x, unsigned height, std::pair & splitter) { assert(size() <= max_nelements()); splitter.first = key_compare::max_value(); value_type Key2Search(x.first, bid_type()); block_iterator it = std::lower_bound(block_->begin(), block_->begin() + size(), Key2Search, vcmp_); assert(it != (block_->begin() + size())); bid_type found_bid = it->second; STXXL_UNUSED(found_bid); if (height == 2) // found_bid points to a leaf { STXXL_VERBOSE1("btree::normal_node Inserting new value into a leaf"); leaf_type * Leaf = btree_->leaf_cache_.get_node((leaf_bid_type)it->second, true); assert(Leaf); std::pair BotSplitter; std::pair result = Leaf->insert(x, BotSplitter); btree_->leaf_cache_.unfix_node((leaf_bid_type)it->second); //if(key_compare::max_value() == BotSplitter.first) if (!(cmp_(key_compare::max_value(), BotSplitter.first) || cmp_(BotSplitter.first, key_compare::max_value()))) return result; // no overflow/splitting happened STXXL_VERBOSE1("btree::normal_node Inserting new value in *this"); splitter = insert(BotSplitter, it); return result; } else { // found_bid points to a node STXXL_VERBOSE1("btree::normal_node Inserting new value into a node"); node_type * Node = btree_->node_cache_.get_node((node_bid_type)it->second, true); assert(Node); std::pair BotSplitter; std::pair result = Node->insert(x, height - 1, BotSplitter); btree_->node_cache_.unfix_node((node_bid_type)it->second); //if(key_compare::max_value() == BotSplitter.first) if (!(cmp_(key_compare::max_value(), BotSplitter.first) || cmp_(BotSplitter.first, key_compare::max_value()))) return result; // no overflow/splitting happened STXXL_VERBOSE1("btree::normal_node Inserting new value in *this"); splitter = insert(BotSplitter, it); return result; } } iterator begin(unsigned height) { bid_type FirstBid = block_->begin()->second; if (height == 2) // FirstBid points to a leaf { assert(size() > 1); STXXL_VERBOSE1("btree::node retrieveing begin() from the first leaf"); leaf_type * Leaf = btree_->leaf_cache_.get_node((leaf_bid_type)FirstBid); assert(Leaf); return Leaf->begin(); } else { // FirstBid points to a node STXXL_VERBOSE1("btree: retrieveing begin() from the first node"); node_type * Node = btree_->node_cache_.get_node((node_bid_type)FirstBid, true); assert(Node); iterator result = Node->begin(height - 1); btree_->node_cache_.unfix_node((node_bid_type)FirstBid); return result; } } const_iterator begin(unsigned height) const { bid_type FirstBid = block_->begin()->second; if (height == 2) // FirstBid points to a leaf { assert(size() > 1); STXXL_VERBOSE1("btree::node retrieveing begin() from the first leaf"); leaf_type const * Leaf = btree_->leaf_cache_.get_const_node((leaf_bid_type)FirstBid); assert(Leaf); return Leaf->begin(); } else { // FirstBid points to a node STXXL_VERBOSE1("btree: retrieveing begin() from the first node"); node_type const * Node = btree_->node_cache_.get_const_node((node_bid_type)FirstBid, true); assert(Node); const_iterator result = Node->begin(height - 1); btree_->node_cache_.unfix_node((node_bid_type)FirstBid); return result; } } iterator find(const key_type & k, unsigned height) { value_type Key2Search(k, bid_type()); block_iterator it = std::lower_bound(block_->begin(), block_->begin() + size(), Key2Search, vcmp_); assert(it != (block_->begin() + size())); bid_type found_bid = it->second; if (height == 2) // found_bid points to a leaf { STXXL_VERBOSE1("Searching in a leaf"); leaf_type * Leaf = btree_->leaf_cache_.get_node((leaf_bid_type)found_bid, true); assert(Leaf); iterator result = Leaf->find(k); btree_->leaf_cache_.unfix_node((leaf_bid_type)found_bid); return result; } // found_bid points to a node STXXL_VERBOSE1("Searching in a node"); node_type * Node = btree_->node_cache_.get_node((node_bid_type)found_bid, true); assert(Node); iterator result = Node->find(k, height - 1); btree_->node_cache_.unfix_node((node_bid_type)found_bid); return result; } const_iterator find(const key_type & k, unsigned height) const { value_type Key2Search(k, bid_type()); block_iterator it = std::lower_bound(block_->begin(), block_->begin() + size(), Key2Search, vcmp_); assert(it != (block_->begin() + size())); bid_type found_bid = it->second; if (height == 2) // found_bid points to a leaf { STXXL_VERBOSE1("Searching in a leaf"); leaf_type const * Leaf = btree_->leaf_cache_.get_const_node((leaf_bid_type)found_bid, true); assert(Leaf); const_iterator result = Leaf->find(k); btree_->leaf_cache_.unfix_node((leaf_bid_type)found_bid); return result; } // found_bid points to a node STXXL_VERBOSE1("Searching in a node"); node_type const * Node = btree_->node_cache_.get_const_node((node_bid_type)found_bid, true); assert(Node); const_iterator result = Node->find(k, height - 1); btree_->node_cache_.unfix_node((node_bid_type)found_bid); return result; } iterator lower_bound(const key_type & k, unsigned height) { value_type Key2Search(k, bid_type()); assert(!vcmp_(back(), Key2Search)); block_iterator it = std::lower_bound(block_->begin(), block_->begin() + size(), Key2Search, vcmp_); assert(it != (block_->begin() + size())); bid_type found_bid = it->second; if (height == 2) // found_bid points to a leaf { STXXL_VERBOSE1("Searching lower bound in a leaf"); leaf_type * Leaf = btree_->leaf_cache_.get_node((leaf_bid_type)found_bid, true); assert(Leaf); iterator result = Leaf->lower_bound(k); btree_->leaf_cache_.unfix_node((leaf_bid_type)found_bid); return result; } // found_bid points to a node STXXL_VERBOSE1("Searching lower bound in a node"); node_type * Node = btree_->node_cache_.get_node((node_bid_type)found_bid, true); assert(Node); iterator result = Node->lower_bound(k, height - 1); btree_->node_cache_.unfix_node((node_bid_type)found_bid); return result; } const_iterator lower_bound(const key_type & k, unsigned height) const { value_type Key2Search(k, bid_type()); assert(!vcmp_(back(), Key2Search)); block_iterator it = std::lower_bound(block_->begin(), block_->begin() + size(), Key2Search, vcmp_); assert(it != (block_->begin() + size())); bid_type found_bid = it->second; if (height == 2) // found_bid points to a leaf { STXXL_VERBOSE1("Searching lower bound in a leaf"); leaf_type const * Leaf = btree_->leaf_cache_.get_const_node((leaf_bid_type)found_bid, true); assert(Leaf); const_iterator result = Leaf->lower_bound(k); btree_->leaf_cache_.unfix_node((leaf_bid_type)found_bid); return result; } // found_bid points to a node STXXL_VERBOSE1("Searching lower bound in a node"); node_type const * Node = btree_->node_cache_.get_const_node((node_bid_type)found_bid, true); assert(Node); const_iterator result = Node->lower_bound(k, height - 1); btree_->node_cache_.unfix_node((node_bid_type)found_bid); return result; } iterator upper_bound(const key_type & k, unsigned height) { value_type Key2Search(k, bid_type()); assert(vcmp_(Key2Search, back())); block_iterator it = std::upper_bound(block_->begin(), block_->begin() + size(), Key2Search, vcmp_); assert(it != (block_->begin() + size())); bid_type found_bid = it->second; if (height == 2) // found_bid points to a leaf { STXXL_VERBOSE1("Searching upper bound in a leaf"); leaf_type * Leaf = btree_->leaf_cache_.get_node((leaf_bid_type)found_bid, true); assert(Leaf); iterator result = Leaf->upper_bound(k); btree_->leaf_cache_.unfix_node((leaf_bid_type)found_bid); return result; } // found_bid points to a node STXXL_VERBOSE1("Searching upper bound in a node"); node_type * Node = btree_->node_cache_.get_node((node_bid_type)found_bid, true); assert(Node); iterator result = Node->upper_bound(k, height - 1); btree_->node_cache_.unfix_node((node_bid_type)found_bid); return result; } const_iterator upper_bound(const key_type & k, unsigned height) const { value_type Key2Search(k, bid_type()); assert(vcmp_(Key2Search, back())); block_iterator it = std::upper_bound(block_->begin(), block_->begin() + size(), Key2Search, vcmp_); assert(it != (block_->begin() + size())); bid_type found_bid = it->second; if (height == 2) // found_bid points to a leaf { STXXL_VERBOSE1("Searching upper bound in a leaf"); leaf_type const * Leaf = btree_->leaf_cache_.get_const_node((leaf_bid_type)found_bid, true); assert(Leaf); const_iterator result = Leaf->upper_bound(k); btree_->leaf_cache_.unfix_node((leaf_bid_type)found_bid); return result; } // found_bid points to a node STXXL_VERBOSE1("Searching upper bound in a node"); node_type const * Node = btree_->node_cache_.get_const_node((node_bid_type)found_bid, true); assert(Node); const_iterator result = Node->upper_bound(k, height - 1); btree_->node_cache_.unfix_node((node_bid_type)found_bid); return result; } void fuse(const normal_node & Src) { assert(vcmp_(Src.back(), front())); const unsigned SrcSize = Src.size(); block_iterator cur = block_->begin() + size() - 1; block_const_iterator begin = block_->begin(); for ( ; cur >= begin; --cur) *(cur + SrcSize) = *cur; // move elements to make space for Src elements // copy Src to *this leaf std::copy(Src.block_->begin(), Src.block_->begin() + SrcSize, block_->begin()); block_->info.cur_size += SrcSize; } key_type balance(normal_node & Left) { const unsigned TotalSize = Left.size() + size(); unsigned newLeftSize = TotalSize / 2; assert(newLeftSize <= Left.max_nelements()); assert(newLeftSize >= Left.min_nelements()); unsigned newRightSize = TotalSize - newLeftSize; assert(newRightSize <= max_nelements()); assert(newRightSize >= min_nelements()); assert(vcmp_(Left.back(), front()) || size() == 0); if (newLeftSize < Left.size()) { const unsigned nEl2Move = Left.size() - newLeftSize; // #elements to move from Left to *this block_iterator cur = block_->begin() + size() - 1; block_const_iterator begin = block_->begin(); for ( ; cur >= begin; --cur) *(cur + nEl2Move) = *cur; // move elements to make space for Src elements // copy Left to *this leaf std::copy(Left.block_->begin() + newLeftSize, Left.block_->begin() + Left.size(), block_->begin()); } else { assert(newRightSize < size()); const unsigned nEl2Move = size() - newRightSize; // #elements to move from *this to Left // copy *this to Left std::copy(block_->begin(), block_->begin() + nEl2Move, Left.block_->begin() + Left.size()); // move elements in *this std::copy(block_->begin() + nEl2Move, block_->begin() + size(), block_->begin()); } block_->info.cur_size = newRightSize; // update size Left.block_->info.cur_size = newLeftSize; // update size return Left.back().first; } size_type erase(const key_type & k, unsigned height) { value_type Key2Search(k, bid_type()); block_iterator it = std::lower_bound(block_->begin(), block_->begin() + size(), Key2Search, vcmp_); assert(it != (block_->begin() + size())); bid_type found_bid = it->second; assert(size() >= 2); if (height == 2) // 'found_bid' points to a leaf { STXXL_VERBOSE1("btree::normal_node Deleting key from a leaf"); leaf_type * Leaf = btree_->leaf_cache_.get_node((leaf_bid_type)found_bid, true); assert(Leaf); size_type result = Leaf->erase(k); btree_->leaf_cache_.unfix_node((leaf_bid_type)it->second); if (!Leaf->underflows()) return result; // no underflow or root has a special degree 1 (too few elements) STXXL_VERBOSE1("btree::normal_node Fusing or rebalancing a leaf"); fuse_or_balance(it, btree_->leaf_cache_); return result; } // 'found_bid' points to a node STXXL_VERBOSE1("btree::normal_node Deleting key from a node"); node_type * Node = btree_->node_cache_.get_node((node_bid_type)found_bid, true); assert(Node); size_type result = Node->erase(k, height - 1); btree_->node_cache_.unfix_node((node_bid_type)found_bid); if (!Node->underflows()) return result; // no underflow happened STXXL_VERBOSE1("btree::normal_node Fusing or rebalancing a node"); fuse_or_balance(it, btree_->node_cache_); return result; } void deallocate_children(unsigned height) { if (height == 2) { // we have children leaves here block_const_iterator it = block().begin(); for ( ; it != block().begin() + size(); ++it) { // delete from leaf cache and deallocate bid btree_->leaf_cache_.delete_node((leaf_bid_type)it->second); } } else { block_const_iterator it = block().begin(); for ( ; it != block().begin() + size(); ++it) { node_type * Node = btree_->node_cache_.get_node((node_bid_type)it->second); assert(Node); Node->deallocate_children(height - 1); // delete from node cache and deallocate bid btree_->node_cache_.delete_node((node_bid_type)it->second); } } } void push_back(const value_type & x) { (*this)[size()] = x; ++(block_->info.cur_size); } }; } __STXXL_END_NAMESPACE #endif /* STXXL_CONTAINERS_BTREE__NODE_H */ stxxl-1.3.1/include/stxxl/bits/containers/btree/iterator_map.h0000644000175000017500000001175011136120570024365 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/containers/btree/iterator_map.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2006 Roman Dementiev * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_CONTAINERS_BTREE__ITERATOR_MAP_H #define STXXL_CONTAINERS_BTREE__ITERATOR_MAP_H #include #include #include #include __STXXL_BEGIN_NAMESPACE namespace btree { template class iterator_map : private noncopyable { public: typedef BTreeType btree_type; typedef typename btree_type::leaf_bid_type bid_type; typedef btree_iterator_base iterator_base; private: struct Key { bid_type bid; unsigned pos; Key() { } Key(const bid_type & b, unsigned p) : bid(b), pos(p) { } }; struct bid_comp { bool operator () (const bid_type & a, const bid_type & b) const { return (a.storage < b.storage) || (a.storage == b.storage && a.offset < b.offset); } }; struct KeyCmp { bid_comp BIDComp; bool operator () (const Key & a, const Key & b) const { return BIDComp(a.bid, b.bid) || (a.bid == b.bid && a.pos < b.pos); } }; typedef std::multimap multimap_type; multimap_type It2Addr_; btree_type * btree_; typedef typename multimap_type::value_type pair_type; typedef typename multimap_type::iterator mmiterator_type; typedef typename multimap_type::const_iterator mmconst_iterator_type; // changes btree pointer in all contained iterators void change_btree_pointers(btree_type * b) { mmconst_iterator_type it = It2Addr_.begin(); for ( ; it != It2Addr_.end(); ++it) { (it->second)->btree_ = b; } } public: iterator_map(btree_type * b) : btree_(b) { } void register_iterator(iterator_base & it) { STXXL_VERBOSE2("btree::iterator_map register_iterator addr=" << &it << " BID: " << it.bid << " POS: " << it.pos); It2Addr_.insert(pair_type(Key(it.bid, it.pos), &it)); } void unregister_iterator(iterator_base & it) { STXXL_VERBOSE2("btree::iterator_map unregister_iterator addr=" << &it << " BID: " << it.bid << " POS: " << it.pos); assert(!It2Addr_.empty()); Key key(it.bid, it.pos); std::pair range = It2Addr_.equal_range(key); assert(range.first != range.second); mmiterator_type i = range.first; for ( ; i != range.second; ++i) { assert(it.bid == (*i).first.bid); assert(it.pos == (*i).first.pos); if ((*i).second == &it) { // found it It2Addr_.erase(i); return; } } STXXL_THROW(std::runtime_error, "unregister_iterator", "Panic in btree::iterator_map, can not find and unregister iterator"); } template void find(const bid_type & bid, unsigned first_pos, unsigned last_pos, OutputContainer & out ) { Key firstkey(bid, first_pos); Key lastkey(bid, last_pos); mmconst_iterator_type begin = It2Addr_.lower_bound(firstkey); mmconst_iterator_type end = It2Addr_.upper_bound(lastkey); mmconst_iterator_type i = begin; for ( ; i != end; ++i) { assert(bid == (*i).first.bid); out.push_back((*i).second); } } virtual ~iterator_map() { mmconst_iterator_type it = It2Addr_.begin(); for ( ; it != It2Addr_.end(); ++it) (it->second)->make_invalid(); } void swap(iterator_map & obj) { std::swap(It2Addr_, obj.It2Addr_); change_btree_pointers(btree_); obj.change_btree_pointers(obj.btree_); } }; } __STXXL_END_NAMESPACE namespace std { template void swap(stxxl::btree::iterator_map & a, stxxl::btree::iterator_map & b) { a.swap(b); } } #endif /* STXXL_CONTAINERS_BTREE__ITERATOR_MAP_H */ stxxl-1.3.1/include/stxxl/bits/containers/btree/leaf.h0000644000175000017500000006170211032363313022607 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/containers/btree/leaf.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2006 Roman Dementiev * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_CONTAINERS_BTREE__LEAF_H #define STXXL_CONTAINERS_BTREE__LEAF_H #include #include __STXXL_BEGIN_NAMESPACE namespace btree { template class node_cache; template class normal_leaf : private noncopyable { public: typedef normal_leaf SelfType; friend class node_cache; typedef KeyType_ key_type; typedef DataType_ data_type; typedef KeyCmp_ key_compare; typedef std::pair value_type; typedef value_type & reference; typedef const value_type & const_reference; enum { raw_size = RawSize_ }; typedef BID bid_type; struct InfoType { bid_type me, pred, succ; unsigned cur_size; }; typedef typed_block block_type; enum { nelements = block_type::size - 1, max_size = nelements, min_size = nelements / 2 }; typedef BTreeType btree_type; typedef typename btree_type::size_type size_type; typedef btree_iterator_base iterator_base; typedef btree_iterator iterator; typedef btree_const_iterator const_iterator; typedef node_cache leaf_cache_type; public: struct value_compare : public std::binary_function { key_compare comp; value_compare(key_compare c) : comp(c) { } bool operator () (const value_type & x, const value_type & y) const { return comp(x.first, y.first); } }; private: block_type * block_; btree_type * btree_; key_compare cmp_; value_compare vcmp_; void split(std::pair & splitter) { bid_type NewBid; btree_->leaf_cache_.get_new_node(NewBid); // new (left) leaf normal_leaf * NewLeaf = btree_->leaf_cache_.get_node(NewBid, true); assert(NewLeaf); // update links NewLeaf->succ() = my_bid(); normal_leaf * PredLeaf = NULL; if (pred().valid()) { NewLeaf->pred() = pred(); PredLeaf = btree_->leaf_cache_.get_node(pred()); assert(PredLeaf); assert(vcmp_(PredLeaf->back(), front())); PredLeaf->succ() = NewBid; } pred() = NewBid; std::vector Iterators2Fix; btree_->iterator_map_.find(my_bid(), 0, size(), Iterators2Fix); const unsigned end_of_smaller_part = size() / 2; splitter.first = ((*block_)[end_of_smaller_part - 1]).first; splitter.second = NewBid; const unsigned old_size = size(); // copy the smaller part std::copy(block_->begin(), block_->begin() + end_of_smaller_part, NewLeaf->block_->begin()); NewLeaf->block_->info.cur_size = end_of_smaller_part; // copy the larger part std::copy(block_->begin() + end_of_smaller_part, block_->begin() + old_size, block_->begin()); block_->info.cur_size = old_size - end_of_smaller_part; assert(size() + NewLeaf->size() == old_size); // fix iterators typename std::vector::iterator it2fix = Iterators2Fix.begin(); for ( ; it2fix != Iterators2Fix.end(); ++it2fix) { btree_->iterator_map_.unregister_iterator(**it2fix); if ((*it2fix)->pos < end_of_smaller_part) // belongs to the smaller part (*it2fix)->bid = NewBid; else (*it2fix)->pos -= end_of_smaller_part; btree_->iterator_map_.register_iterator(**it2fix); } STXXL_VERBOSE1("btree::normal_leaf split leaf " << this << " splitter: " << splitter.first); #if STXXL_VERBOSE_LEVEL >= 1 if (PredLeaf) { STXXL_VERBOSE1("btree::normal_leaf pred_part.smallest = " << PredLeaf->front().first); STXXL_VERBOSE1("btree::normal_leaf pred_part.largest = " << PredLeaf->back().first); } #endif STXXL_VERBOSE1("btree::normal_leaf smaller_part.smallest = " << NewLeaf->front().first); STXXL_VERBOSE1("btree::normal_leaf smaller_part.largest = " << NewLeaf->back().first); STXXL_VERBOSE1("btree::normal_leaf larger_part.smallest = " << front().first); STXXL_VERBOSE1("btree::normal_leaf larger_part.largest = " << back().first); btree_->leaf_cache_.unfix_node(NewBid); } public: virtual ~normal_leaf() { delete block_; } normal_leaf(btree_type * btree__, key_compare cmp) : block_(new block_type), btree_(btree__), cmp_(cmp), vcmp_(cmp) { assert(min_nelements() >= 2); assert(2 * min_nelements() - 1 <= max_nelements()); assert(max_nelements() <= nelements); assert(unsigned(block_type::size) >= nelements + 1); // extra space for an overflow } bool overflows() const { return block_->info.cur_size > max_nelements(); } bool underflows() const { return block_->info.cur_size < min_nelements(); } unsigned max_nelements() const { return max_size; } unsigned min_nelements() const { return min_size; } bid_type & succ() { return block_->info.succ; } bid_type & pred() { return block_->info.pred; } const bid_type & succ() const { return block_->info.succ; } const bid_type & pred() const { return block_->info.pred; } /* template normal_leaf(InputIterator begin_, InputIterator end_, btree_type * btree__, key_compare cmp): block_(new block_type), btree_(btree__), cmp_(cmp), vcmp_(cmp) { assert(min_nelements() >=2); assert(2*min_nelements() - 1 <= max_nelements()); assert(max_nelements() <= nelements); assert(unsigned(block_type::size) >= nelements +1); // extra space for an overflow element unsigned new_size = end_ - begin_; assert(new_size <= max_nelements()); assert(new_size >= min_nelements()); std::copy(begin_,end_,block_->begin()); assert(stxxl::is_sorted(block_->begin(),block_->begin() + new_size, vcmp_)); block_->info.cur_size = new_size; }*/ unsigned size() const { return block_->info.cur_size; } const bid_type & my_bid() const { return block_->info.me; } void save() { request_ptr req = block_->write(my_bid()); req->wait(); } request_ptr load(const bid_type & bid) { request_ptr req = block_->read(bid); req->wait(); assert(bid == my_bid()); return req; } request_ptr prefetch(const bid_type & bid) { return block_->read(bid); } void init(const bid_type & my_bid_) { block_->info.me = my_bid_; block_->info.succ = bid_type(); block_->info.pred = bid_type(); block_->info.cur_size = 0; } reference operator [] (int i) { return (*block_)[i]; } const_reference operator [] (int i) const { return (*block_)[i]; } reference back() { return (*block_)[size() - 1]; } reference front() { return *(block_->begin()); } const_reference back() const { return (*block_)[size() - 1]; } const_reference front() const { return *(block_->begin()); } void dump() { STXXL_VERBOSE2("Dump of leaf " << this); for (unsigned i = 0; i < size(); ++i) STXXL_VERBOSE2((*this)[i].first << " " << (*this)[i].second); } std::pair insert( const value_type & x, std::pair & splitter) { assert(size() <= max_nelements()); splitter.first = key_compare::max_value(); typename block_type::iterator it = std::lower_bound(block_->begin(), block_->begin() + size(), x, vcmp_); if (!(vcmp_(*it, x) || vcmp_(x, *it)) && it != (block_->begin() + size())) // *it == x { // already exists return std::pair( iterator(btree_, my_bid(), it - block_->begin()), false); } typename block_type::iterator cur = block_->begin() + size() - 1; for ( ; cur >= it; --cur) *(cur + 1) = *cur; // move elements to make space for the new element *it = x; std::vector Iterators2Fix; btree_->iterator_map_.find(my_bid(), it - block_->begin(), size(), Iterators2Fix); typename std::vector::iterator it2fix = Iterators2Fix.begin(); for ( ; it2fix != Iterators2Fix.end(); ++it2fix) { btree_->iterator_map_.unregister_iterator(**it2fix); ++((*it2fix)->pos); // fixing iterators btree_->iterator_map_.register_iterator(**it2fix); } ++(block_->info.cur_size); std::pair result(iterator(btree_, my_bid(), it - block_->begin()), true); if (size() <= max_nelements()) { // no overflow dump(); return result; } // overflow split(splitter); return result; } iterator begin() { return iterator(btree_, my_bid(), 0); } const_iterator begin() const { return const_iterator(btree_, my_bid(), 0); } iterator end() { return iterator(btree_, my_bid(), size()); } void increment_iterator(iterator_base & it) const { assert(it.bid == my_bid()); assert(it.pos != size()); btree_->iterator_map_.unregister_iterator(it); ++(it.pos); if (it.pos == size() && succ().valid()) { // run to the end of the leaf STXXL_VERBOSE1("btree::normal_leaf jumping to the next block"); it.pos = 0; it.bid = succ(); } else if (it.pos == 1 && btree_->prefetching_enabled_) // increment of pos from 0 to 1 { // prefetch the succ leaf if (succ().valid()) btree_->leaf_cache_.prefetch_node(succ()); } btree_->iterator_map_.register_iterator(it); } void decrement_iterator(iterator_base & it) const { assert(it.bid == my_bid()); btree_->iterator_map_.unregister_iterator(it); if (it.pos == 0) { assert(pred().valid()); it.bid = pred(); normal_leaf const * PredLeaf = btree_->leaf_cache_.get_const_node(pred(), true); assert(PredLeaf); it.pos = PredLeaf->size() - 1; // prefetch the pred leaf of PredLeaf if (btree_->prefetching_enabled_ && PredLeaf->pred().valid()) btree_->leaf_cache_.prefetch_node(PredLeaf->pred()); btree_->leaf_cache_.unfix_node(pred()); } else --it.pos; btree_->iterator_map_.register_iterator(it); } iterator find(const key_type & k) { value_type searchVal(k, data_type()); typename block_type::iterator lb = std::lower_bound(block_->begin(), block_->begin() + size(), searchVal, vcmp_); if (lb == block_->begin() + size() || lb->first != k) return btree_->end(); return iterator(btree_, my_bid(), lb - block_->begin()); } const_iterator find(const key_type & k) const { value_type searchVal(k, data_type()); typename block_type::iterator lb = std::lower_bound(block_->begin(), block_->begin() + size(), searchVal, vcmp_); if (lb == block_->begin() + size() || lb->first != k) return btree_->end(); return const_iterator(btree_, my_bid(), lb - block_->begin()); } iterator lower_bound(const key_type & k) { value_type searchVal(k, data_type()); typename block_type::iterator lb = std::lower_bound(block_->begin(), block_->begin() + size(), searchVal, vcmp_); // lower_bound is in the succ block if (lb == block_->begin() + size() && succ().valid()) { return iterator(btree_, succ(), 0); } return iterator(btree_, my_bid(), lb - block_->begin()); } const_iterator lower_bound(const key_type & k) const { value_type searchVal(k, data_type()); typename block_type::iterator lb = std::lower_bound(block_->begin(), block_->begin() + size(), searchVal, vcmp_); // lower_bound is in the succ block if (lb == block_->begin() + size() && succ().valid()) { return iterator(btree_, succ(), 0); } return const_iterator(btree_, my_bid(), lb - block_->begin()); } iterator upper_bound(const key_type & k) { value_type searchVal(k, data_type()); typename block_type::iterator lb = std::upper_bound(block_->begin(), block_->begin() + size(), searchVal, vcmp_); // upper_bound is in the succ block if (lb == block_->begin() + size() && succ().valid()) { return iterator(btree_, succ(), 0); } return iterator(btree_, my_bid(), lb - block_->begin()); } const_iterator upper_bound(const key_type & k) const { value_type searchVal(k, data_type()); typename block_type::iterator lb = std::upper_bound(block_->begin(), block_->begin() + size(), searchVal, vcmp_); // upper_bound is in the succ block if (lb == block_->begin() + size() && succ().valid()) { return const_iterator(btree_, succ(), 0); } return const_iterator(btree_, my_bid(), lb - block_->begin()); } size_type erase(const key_type & k) { value_type searchVal(k, data_type()); typename block_type::iterator it = std::lower_bound(block_->begin(), block_->begin() + size(), searchVal, vcmp_); if (it == block_->begin() + size() || it->first != k) return 0; // no such element // move elements one position left std::copy(it + 1, block_->begin() + size(), it); std::vector Iterators2Fix; btree_->iterator_map_.find(my_bid(), it + 1 - block_->begin(), size(), Iterators2Fix); typename std::vector::iterator it2fix = Iterators2Fix.begin(); for ( ; it2fix != Iterators2Fix.end(); ++it2fix) { STXXL_VERBOSE2("btree::normal_leaf updating iterator " << (*it2fix) << " (pos--)"); btree_->iterator_map_.unregister_iterator(**it2fix); --((*it2fix)->pos); // fixing iterators btree_->iterator_map_.register_iterator(**it2fix); } --(block_->info.cur_size); return 1; } void fuse(const normal_leaf & Src) { STXXL_VERBOSE1("btree::normal_leaf Fusing"); assert(vcmp_(Src.back(), front())); const unsigned SrcSize = Src.size(); typename block_type::iterator cur = block_->begin() + size() - 1; typename block_type::const_iterator begin = block_->begin(); for ( ; cur >= begin; --cur) *(cur + SrcSize) = *cur; // move elements to make space for Src elements // copy Src to *this leaf std::copy(Src.block_->begin(), Src.block_->begin() + SrcSize, block_->begin()); std::vector Iterators2Fix; btree_->iterator_map_.find(my_bid(), 0, size(), Iterators2Fix); typename std::vector::iterator it2fix = Iterators2Fix.begin(); for ( ; it2fix != Iterators2Fix.end(); ++it2fix) { STXXL_VERBOSE2("btree::normal_leaf updating iterator " << (*it2fix) << " (pos+" << SrcSize << ")"); btree_->iterator_map_.unregister_iterator(**it2fix); ((*it2fix)->pos) += SrcSize; // fixing iterators btree_->iterator_map_.register_iterator(**it2fix); } Iterators2Fix.clear(); btree_->iterator_map_.find(Src.my_bid(), 0, SrcSize, Iterators2Fix); it2fix = Iterators2Fix.begin(); for ( ; it2fix != Iterators2Fix.end(); ++it2fix) { STXXL_VERBOSE2("btree::normal_leaf updating iterator " << (*it2fix) << " (bid=" << my_bid() << ")"); btree_->iterator_map_.unregister_iterator(**it2fix); ((*it2fix)->bid) = my_bid(); // fixing iterators btree_->iterator_map_.register_iterator(**it2fix); } block_->info.cur_size += SrcSize; // update links pred() = Src.pred(); if (pred().valid()) { // update successor link normal_leaf * NewPred = btree_->leaf_cache_.get_node(pred()); assert(NewPred); NewPred->succ() = my_bid(); } } key_type balance(normal_leaf & Left) { STXXL_VERBOSE1("btree::normal_leaf Balancing leaves with bids " << Left.my_bid() << " and " << my_bid()); const unsigned TotalSize = Left.size() + size(); unsigned newLeftSize = TotalSize / 2; assert(newLeftSize <= Left.max_nelements()); assert(newLeftSize >= Left.min_nelements()); unsigned newRightSize = TotalSize - newLeftSize; assert(newRightSize <= max_nelements()); assert(newRightSize >= min_nelements()); assert(vcmp_(Left.back(), front()) || size() == 0); if (newLeftSize < Left.size()) { const unsigned nEl2Move = Left.size() - newLeftSize; // #elements to move from Left to *this typename block_type::iterator cur = block_->begin() + size() - 1; typename block_type::const_iterator begin = block_->begin(); for ( ; cur >= begin; --cur) *(cur + nEl2Move) = *cur; // move elements to make space for Src elements // copy Left to *this leaf std::copy(Left.block_->begin() + newLeftSize, Left.block_->begin() + Left.size(), block_->begin()); std::vector Iterators2Fix1; std::vector Iterators2Fix2; btree_->iterator_map_.find(my_bid(), 0, size(), Iterators2Fix1); btree_->iterator_map_.find(Left.my_bid(), newLeftSize, Left.size(), Iterators2Fix2); typename std::vector::iterator it2fix = Iterators2Fix1.begin(); for ( ; it2fix != Iterators2Fix1.end(); ++it2fix) { STXXL_VERBOSE2("btree::normal_leaf updating iterator " << (*it2fix) << " (pos+" << nEl2Move << ")"); btree_->iterator_map_.unregister_iterator(**it2fix); ((*it2fix)->pos) += nEl2Move; // fixing iterators btree_->iterator_map_.register_iterator(**it2fix); } it2fix = Iterators2Fix2.begin(); for ( ; it2fix != Iterators2Fix2.end(); ++it2fix) { STXXL_VERBOSE2("btree::normal_leaf updating iterator " << (*it2fix) << " (pos-" << newLeftSize << " bid=" << my_bid() << ")"); btree_->iterator_map_.unregister_iterator(**it2fix); ((*it2fix)->bid) = my_bid(); // fixing iterators ((*it2fix)->pos) -= newLeftSize; // fixing iterators btree_->iterator_map_.register_iterator(**it2fix); } } else { assert(newRightSize < size()); const unsigned nEl2Move = size() - newRightSize; // #elements to move from *this to Left // copy *this to Left std::copy(block_->begin(), block_->begin() + nEl2Move, Left.block_->begin() + Left.size()); // move elements in *this std::copy(block_->begin() + nEl2Move, block_->begin() + size(), block_->begin()); std::vector Iterators2Fix1; std::vector Iterators2Fix2; btree_->iterator_map_.find(my_bid(), nEl2Move, size(), Iterators2Fix1); btree_->iterator_map_.find(my_bid(), 0, nEl2Move - 1, Iterators2Fix2); typename std::vector::iterator it2fix = Iterators2Fix1.begin(); for ( ; it2fix != Iterators2Fix1.end(); ++it2fix) { STXXL_VERBOSE2("btree::normal_leaf updating iterator " << (*it2fix) << " (pos-" << nEl2Move << ")"); btree_->iterator_map_.unregister_iterator(**it2fix); ((*it2fix)->pos) -= nEl2Move; // fixing iterators btree_->iterator_map_.register_iterator(**it2fix); } it2fix = Iterators2Fix2.begin(); for ( ; it2fix != Iterators2Fix2.end(); ++it2fix) { STXXL_VERBOSE2("btree::normal_leaf updating iterator " << (*it2fix) << " (pos+" << Left.size() << " bid=" << Left.my_bid() << ")"); btree_->iterator_map_.unregister_iterator(**it2fix); ((*it2fix)->bid) = Left.my_bid(); // fixing iterators ((*it2fix)->pos) += Left.size(); // fixing iterators btree_->iterator_map_.register_iterator(**it2fix); } } block_->info.cur_size = newRightSize; // update size Left.block_->info.cur_size = newLeftSize; // update size return Left.back().first; } void push_back(const value_type & x) { (*this)[size()] = x; ++(block_->info.cur_size); } }; } __STXXL_END_NAMESPACE #endif /* STXXL_CONTAINERS_BTREE__LEAF_H */ stxxl-1.3.1/include/stxxl/bits/containers/btree/node_cache.h0000644000175000017500000004773711535513725024000 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/containers/btree/node_cache.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2006 Roman Dementiev * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_CONTAINERS_BTREE__NODE_CACHE_H #define STXXL_CONTAINERS_BTREE__NODE_CACHE_H #ifdef STXXL_BOOST_CONFIG #include #endif #include #include #include #include #include #include __STXXL_BEGIN_NAMESPACE // TODO: speedup BID2node_ access using search result iterator in the methods namespace btree { template class node_cache : private noncopyable { public: typedef BTreeType btree_type; typedef NodeType node_type; typedef typename node_type::block_type block_type; typedef typename node_type::bid_type bid_type; typedef typename btree_type::key_compare key_compare; typedef typename btree_type::alloc_strategy_type alloc_strategy_type; typedef stxxl::lru_pager<> pager_type; private: btree_type * btree_; key_compare comp_; /* struct bid_comp { bool operator () (const bid_type & a, const bid_type & b) const { return (a.storage < b.storage) || ( a.storage == b.storage && a.offset < b.offset); } }; */ struct bid_hash { size_t operator () (const bid_type & bid) const { size_t result = longhash1(bid.offset + uint64(unsigned_type(bid.storage))); return result; } #ifdef BOOST_MSVC bool operator () (const bid_type & a, const bid_type & b) const { return (a.storage < b.storage) || (a.storage == b.storage && a.offset < b.offset); } enum { // parameters for hash table bucket_size = 4, // 0 < bucket_size min_buckets = 8 // min_buckets = 2 ^^ N, 0 < N }; #endif }; std::vector nodes_; std::vector reqs_; std::vector fixed_; std::vector dirty_; std::vector free_nodes_; typedef typename compat_hash_map::result hash_map_type; //typedef std::map BID2node_type; typedef hash_map_type BID2node_type; BID2node_type BID2node_; pager_type pager_; block_manager * bm; alloc_strategy_type alloc_strategy_; int64 n_found; int64 n_not_found; int64 n_created; int64 n_deleted; int64 n_read; int64 n_written; int64 n_clean_forced; // changes btree pointer in all contained iterators void change_btree_pointers(btree_type * b) { typename std::vector::const_iterator it = nodes_.begin(); for ( ; it != nodes_.end(); ++it) { (*it)->btree_ = b; } } public: node_cache(unsigned_type cache_size_in_bytes, btree_type * btree__, key_compare comp__ ) : btree_(btree__), comp_(comp__), bm(block_manager::get_instance()), n_found(0), n_not_found(0), n_created(0), n_deleted(0), n_read(0), n_written(0), n_clean_forced(0) { const unsigned_type nnodes = cache_size_in_bytes / block_type::raw_size; STXXL_VERBOSE1("btree::node_cache constructor nodes=" << nnodes); if (nnodes < 3) { STXXL_THROW(std::runtime_error, "btree::node_cache::node_cache", "Too few memory for a node cache (<3)"); } nodes_.reserve(nnodes); reqs_.resize(nnodes); free_nodes_.reserve(nnodes); fixed_.resize(nnodes, false); dirty_.resize(nnodes, true); for (unsigned_type i = 0; i < nnodes; ++i) { nodes_.push_back(new node_type(btree_, comp_)); free_nodes_.push_back(i); } pager_type tmp_pager(nnodes); std::swap(pager_, tmp_pager); } unsigned_type size() const { return nodes_.size(); } // returns the number of fixed pages unsigned_type nfixed() const { typename BID2node_type::const_iterator i = BID2node_.begin(); typename BID2node_type::const_iterator end = BID2node_.end(); unsigned_type cnt = 0; for ( ; i != end; ++i) { if (fixed_[(*i).second]) ++cnt; } return cnt; } ~node_cache() { STXXL_VERBOSE1("btree::node_cache destructor addr=" << this); typename BID2node_type::const_iterator i = BID2node_.begin(); typename BID2node_type::const_iterator end = BID2node_.end(); for ( ; i != end; ++i) { const unsigned_type p = (*i).second; if (reqs_[p].valid()) reqs_[p]->wait(); if (dirty_[p]) nodes_[p]->save(); } for (unsigned_type i = 0; i < size(); ++i) delete nodes_[i]; } node_type * get_new_node(bid_type & new_bid) { ++n_created; if (free_nodes_.empty()) { // need to kick a node int_type node2kick; unsigned_type i = 0; const unsigned_type max_tries = size() + 1; do { ++i; node2kick = pager_.kick(); if (i == max_tries) { STXXL_ERRMSG( "The node cache is too small, no node can be kicked out (all nodes are fixed) !"); STXXL_ERRMSG("Returning NULL node."); return NULL; } pager_.hit(node2kick); } while (fixed_[node2kick]); if (reqs_[node2kick].valid()) reqs_[node2kick]->wait(); node_type & Node = *(nodes_[node2kick]); if (dirty_[node2kick]) { Node.save(); ++n_written; } else ++n_clean_forced; //reqs_[node2kick] = request_ptr(); // reset request assert(BID2node_.find(Node.my_bid()) != BID2node_.end()); BID2node_.erase(Node.my_bid()); bm->new_block(alloc_strategy_, new_bid); BID2node_[new_bid] = node2kick; Node.init(new_bid); dirty_[node2kick] = true; assert(size() == BID2node_.size() + free_nodes_.size()); STXXL_VERBOSE1("btree::node_cache get_new_node, need to kick node " << node2kick); return &Node; } int_type free_node = free_nodes_.back(); free_nodes_.pop_back(); assert(fixed_[free_node] == false); bm->new_block(alloc_strategy_, new_bid); BID2node_[new_bid] = free_node; node_type & Node = *(nodes_[free_node]); Node.init(new_bid); // assert(!(reqs_[free_node].valid())); pager_.hit(free_node); dirty_[free_node] = true; assert(size() == BID2node_.size() + free_nodes_.size()); STXXL_VERBOSE1("btree::node_cache get_new_node, free node " << free_node << "available"); return &Node; } node_type * get_node(const bid_type & bid, bool fix = false) { typename BID2node_type::const_iterator it = BID2node_.find(bid); ++n_read; if (it != BID2node_.end()) { // the node is in cache const int_type nodeindex = it->second; STXXL_VERBOSE1("btree::node_cache get_node, the node " << nodeindex << "is in cache , fix=" << fix); fixed_[nodeindex] = fix; pager_.hit(nodeindex); dirty_[nodeindex] = true; if (reqs_[nodeindex].valid() && !reqs_[nodeindex]->poll()) reqs_[nodeindex]->wait(); ++n_found; return nodes_[nodeindex]; } ++n_not_found; // the node is not in cache if (free_nodes_.empty()) { // need to kick a node int_type node2kick; unsigned_type i = 0; const unsigned_type max_tries = size() + 1; do { ++i; node2kick = pager_.kick(); if (i == max_tries) { STXXL_ERRMSG( "The node cache is too small, no node can be kicked out (all nodes are fixed) !"); STXXL_ERRMSG("Returning NULL node."); return NULL; } pager_.hit(node2kick); } while (fixed_[node2kick]); if (reqs_[node2kick].valid()) reqs_[node2kick]->wait(); node_type & Node = *(nodes_[node2kick]); if (dirty_[node2kick]) { Node.save(); ++n_written; } else ++n_clean_forced; BID2node_.erase(Node.my_bid()); reqs_[node2kick] = Node.load(bid); BID2node_[bid] = node2kick; fixed_[node2kick] = fix; dirty_[node2kick] = true; assert(size() == BID2node_.size() + free_nodes_.size()); STXXL_VERBOSE1("btree::node_cache get_node, need to kick node" << node2kick << " fix=" << fix); return &Node; } int_type free_node = free_nodes_.back(); free_nodes_.pop_back(); assert(fixed_[free_node] == false); node_type & Node = *(nodes_[free_node]); reqs_[free_node] = Node.load(bid); BID2node_[bid] = free_node; pager_.hit(free_node); fixed_[free_node] = fix; dirty_[free_node] = true; assert(size() == BID2node_.size() + free_nodes_.size()); STXXL_VERBOSE1("btree::node_cache get_node, free node " << free_node << "available, fix=" << fix); return &Node; } node_type const * get_const_node(const bid_type & bid, bool fix = false) { typename BID2node_type::const_iterator it = BID2node_.find(bid); ++n_read; if (it != BID2node_.end()) { // the node is in cache const int_type nodeindex = it->second; STXXL_VERBOSE1("btree::node_cache get_node, the node " << nodeindex << "is in cache , fix=" << fix); fixed_[nodeindex] = fix; pager_.hit(nodeindex); if (reqs_[nodeindex].valid() && !reqs_[nodeindex]->poll()) reqs_[nodeindex]->wait(); ++n_found; return nodes_[nodeindex]; } ++n_not_found; // the node is not in cache if (free_nodes_.empty()) { // need to kick a node int_type node2kick; unsigned_type i = 0; const unsigned_type max_tries = size() + 1; do { ++i; node2kick = pager_.kick(); if (i == max_tries) { STXXL_ERRMSG( "The node cache is too small, no node can be kicked out (all nodes are fixed) !"); STXXL_ERRMSG("Returning NULL node."); return NULL; } pager_.hit(node2kick); } while (fixed_[node2kick]); if (reqs_[node2kick].valid()) reqs_[node2kick]->wait(); node_type & Node = *(nodes_[node2kick]); if (dirty_[node2kick]) { Node.save(); ++n_written; } else ++n_clean_forced; BID2node_.erase(Node.my_bid()); reqs_[node2kick] = Node.load(bid); BID2node_[bid] = node2kick; fixed_[node2kick] = fix; dirty_[node2kick] = false; assert(size() == BID2node_.size() + free_nodes_.size()); STXXL_VERBOSE1("btree::node_cache get_node, need to kick node" << node2kick << " fix=" << fix); return &Node; } int_type free_node = free_nodes_.back(); free_nodes_.pop_back(); assert(fixed_[free_node] == false); node_type & Node = *(nodes_[free_node]); reqs_[free_node] = Node.load(bid); BID2node_[bid] = free_node; pager_.hit(free_node); fixed_[free_node] = fix; dirty_[free_node] = false; assert(size() == BID2node_.size() + free_nodes_.size()); STXXL_VERBOSE1("btree::node_cache get_node, free node " << free_node << "available, fix=" << fix); return &Node; } void delete_node(const bid_type & bid) { typename BID2node_type::const_iterator it = BID2node_.find(bid); try { if (it != BID2node_.end()) { // the node is in the cache const int_type nodeindex = it->second; STXXL_VERBOSE1("btree::node_cache delete_node " << nodeindex << " from cache."); if (reqs_[nodeindex].valid()) reqs_[nodeindex]->wait(); //reqs_[nodeindex] = request_ptr(); // reset request free_nodes_.push_back(nodeindex); BID2node_.erase(bid); fixed_[nodeindex] = false; } ++n_deleted; } catch (const io_error & ex) { bm->delete_block(bid); throw io_error(ex.what()); } bm->delete_block(bid); } void prefetch_node(const bid_type & bid) { if (BID2node_.find(bid) != BID2node_.end()) return; // the node is not in cache if (free_nodes_.empty()) { // need to kick a node int_type node2kick; unsigned_type i = 0; const unsigned_type max_tries = size() + 1; do { ++i; node2kick = pager_.kick(); if (i == max_tries) { STXXL_ERRMSG( "The node cache is too small, no node can be kicked out (all nodes are fixed) !"); STXXL_ERRMSG("Returning NULL node."); return; } pager_.hit(node2kick); } while (fixed_[node2kick]); if (reqs_[node2kick].valid()) reqs_[node2kick]->wait(); node_type & Node = *(nodes_[node2kick]); if (dirty_[node2kick]) { Node.save(); ++n_written; } else ++n_clean_forced; BID2node_.erase(Node.my_bid()); reqs_[node2kick] = Node.prefetch(bid); BID2node_[bid] = node2kick; fixed_[node2kick] = false; dirty_[node2kick] = false; assert(size() == BID2node_.size() + free_nodes_.size()); STXXL_VERBOSE1("btree::node_cache prefetch_node, need to kick node" << node2kick << " "); return; } int_type free_node = free_nodes_.back(); free_nodes_.pop_back(); assert(fixed_[free_node] == false); node_type & Node = *(nodes_[free_node]); reqs_[free_node] = Node.prefetch(bid); BID2node_[bid] = free_node; pager_.hit(free_node); fixed_[free_node] = false; dirty_[free_node] = false; assert(size() == BID2node_.size() + free_nodes_.size()); STXXL_VERBOSE1("btree::node_cache prefetch_node, free node " << free_node << "available"); return; } void unfix_node(const bid_type & bid) { assert(BID2node_.find(bid) != BID2node_.end()); fixed_[BID2node_[bid]] = false; STXXL_VERBOSE1("btree::node_cache unfix_node, node " << BID2node_[bid]); } void swap(node_cache & obj) { std::swap(comp_, obj.comp_); std::swap(nodes_, obj.nodes_); std::swap(reqs_, obj.reqs_); change_btree_pointers(btree_); obj.change_btree_pointers(obj.btree_); std::swap(fixed_, obj.fixed_); std::swap(free_nodes_, obj.free_nodes_); std::swap(BID2node_, obj.BID2node_); std::swap(pager_, obj.pager_); std::swap(alloc_strategy_, obj.alloc_strategy_); std::swap(n_found, obj.n_found); std::swap(n_not_found, obj.n_found); std::swap(n_created, obj.n_created); std::swap(n_deleted, obj.n_deleted); std::swap(n_read, obj.n_read); std::swap(n_written, obj.n_written); std::swap(n_clean_forced, obj.n_clean_forced); } void print_statistics(std::ostream & o) const { if (n_read) o << "Found blocks : " << n_found << " (" << 100. * double(n_found) / double(n_read) << "%)" << std::endl; else o << "Found blocks : " << n_found << " (" << 100 << "%)" << std::endl; o << "Not found blocks : " << n_not_found << std::endl; o << "Created in the cache blocks : " << n_created << std::endl; o << "Deleted blocks : " << n_deleted << std::endl; o << "Read blocks : " << n_read << std::endl; o << "Written blocks : " << n_written << std::endl; o << "Clean blocks forced from the cache: " << n_clean_forced << std::endl; } void reset_statistics() { n_found = 0; n_not_found = 0; n_created = 0; n_deleted = 0; n_read = 0; n_written = 0; n_clean_forced = 0; } }; } __STXXL_END_NAMESPACE namespace std { template void swap(stxxl::btree::node_cache & a, stxxl::btree::node_cache & b) { a.swap(b); } } #endif /* STXXL_CONTAINERS_BTREE__NODE_CACHE_H */ stxxl-1.3.1/include/stxxl/bits/containers/btree/root_node.h0000644000175000017500000000156211026753412023674 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/containers/btree/root_node.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2006 Roman Dementiev * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_CONTAINERS_BTREE__ROOT_NODE_H #define STXXL_CONTAINERS_BTREE__ROOT_NODE_H #include __STXXL_BEGIN_NAMESPACE namespace btree { template class root_node { // a place for a future custom root node tree implementation }; } __STXXL_END_NAMESPACE #endif /* STXXL_CONTAINERS_BTREE__ROOT_NODE_H */ stxxl-1.3.1/include/stxxl/bits/containers/map.h0000644000175000017500000004116211535151017021356 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/containers/map.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2006 Roman Dementiev * Copyright (C) 2008, 2009 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_MAP_HEADER #define STXXL_MAP_HEADER #include #include __STXXL_BEGIN_NAMESPACE namespace btree { template class btree; } //! \addtogroup stlcont //! \{ //! \brief External associative container. //! \tparam KeyType key type (POD with no references to internal memory) //! \tparam DataType data type (POD with no references to internal memory) //! \tparam CompareType comparison type used to determine //! whether a key is smaller than another one. //! If CompareType()(x,y) is true, then x is smaller than y. //! CompareType must also provide a static \c max_value method, that returns //! a value of type KeyType that is //! larger than any key stored in map : i.e. for all \b x in map holds //! CompareType()(x,CompareType::max_value()) //! //!
//! Example: : //! \verbatim //! struct CmpIntGreater //! { //! bool operator () (const int & a, const int & b) const { return a>b; } //! static int max_value() { return std::numeric_limits::min(); } //! }; //! \endverbatim //! Another example: //! \verbatim //! struct CmpIntLess //! { //! bool operator () (const int & a, const int & b) const { return a::max(); } //! }; //! \endverbatim //! Note that CompareType must define a strict weak ordering. //! (see what it is) //! \tparam RawNodeSize size of internal nodes of map in bytes (btree implementation). //! \tparam RawLeafSize size of leaves of map in bytes (btree implementation). //! \tparam PDAllocStrategy parallel disk allocation strategy (\c stxxl::SR is recommended and default) //! template class map : private noncopyable { typedef btree::btree impl_type; impl_type Impl; public: typedef typename impl_type::node_block_type node_block_type; typedef typename impl_type::leaf_block_type leaf_block_type; typedef typename impl_type::key_type key_type; typedef typename impl_type::data_type data_type; typedef typename impl_type::data_type mapped_type; typedef typename impl_type::value_type value_type; typedef typename impl_type::key_compare key_compare; typedef typename impl_type::value_compare value_compare; typedef typename impl_type::pointer pointer; typedef typename impl_type::const_pointer const_pointer; typedef typename impl_type::reference reference; typedef typename impl_type::const_reference const_reference; typedef typename impl_type::size_type size_type; typedef typename impl_type::difference_type difference_type; typedef typename impl_type::iterator iterator; typedef typename impl_type::const_iterator const_iterator; typedef std::reverse_iterator reverse_iterator; typedef std::reverse_iterator const_reverse_iterator; iterator begin() { return Impl.begin(); } iterator end() { return Impl.end(); } const_iterator begin() const { return Impl.begin(); } const_iterator end() const { return Impl.end(); } const_iterator cbegin() const { return begin(); } const_iterator cend() const { return end(); } reverse_iterator rbegin() { return reverse_iterator(end()); } const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); } const_reverse_iterator crbegin() const { return const_reverse_iterator(end()); } reverse_iterator rend() { return reverse_iterator(begin()); } const_reverse_iterator rend() const { return const_reverse_iterator(begin()); } const_reverse_iterator crend() const { return const_reverse_iterator(begin()); } size_type size() const { return Impl.size(); } size_type max_size() const { return Impl.max_size(); } bool empty() const { return Impl.empty(); } key_compare key_comp() const { return Impl.key_comp(); } value_compare value_comp() const { return Impl.value_comp(); } //! \brief A constructor //! \param node_cache_size_in_bytes size of node cache in bytes (btree implementation) //! \param leaf_cache_size_in_bytes size of leaf cache in bytes (btree implementation) map(unsigned_type node_cache_size_in_bytes, unsigned_type leaf_cache_size_in_bytes ) : Impl(node_cache_size_in_bytes, leaf_cache_size_in_bytes) { } //! \brief A constructor //! \param c_ comparator object //! \param node_cache_size_in_bytes size of node cache in bytes (btree implementation) //! \param leaf_cache_size_in_bytes size of leaf cache in bytes (btree implementation) map(const key_compare & c_, unsigned_type node_cache_size_in_bytes, unsigned_type leaf_cache_size_in_bytes ) : Impl(c_, node_cache_size_in_bytes, leaf_cache_size_in_bytes) { } //! \brief Constructs a map from a given input range //! \param b beginning of the range //! \param e end of the range //! \param node_cache_size_in_bytes size of node cache in bytes (btree implementation) //! \param leaf_cache_size_in_bytes size of leaf cache in bytes (btree implementation) //! \param range_sorted if \c true than the constructor assumes that the range is sorted //! and performs a fast bottom-up bulk construction of the map (btree implementation) //! \param node_fill_factor node fill factor in [0,1] for bulk construction //! \param leaf_fill_factor leaf fill factor in [0,1] for bulk construction template map(InputIterator b, InputIterator e, unsigned_type node_cache_size_in_bytes, unsigned_type leaf_cache_size_in_bytes, bool range_sorted = false, double node_fill_factor = 0.75, double leaf_fill_factor = 0.6 ) : Impl(b, e, node_cache_size_in_bytes, leaf_cache_size_in_bytes, range_sorted, node_fill_factor, leaf_fill_factor) { } //! \brief Constructs a map from a given input range //! \param b beginning of the range //! \param e end of the range //! \param c_ comparator object //! \param node_cache_size_in_bytes size of node cache in bytes (btree implementation) //! \param leaf_cache_size_in_bytes size of leaf cache in bytes (btree implementation) //! \param range_sorted if \c true than the constructor assumes that the range is sorted //! and performs a fast bottom-up bulk construction of the map (btree implementation) //! \param node_fill_factor node fill factor in [0,1] for bulk construction //! \param leaf_fill_factor leaf fill factor in [0,1] for bulk construction template map(InputIterator b, InputIterator e, const key_compare & c_, unsigned_type node_cache_size_in_bytes, unsigned_type leaf_cache_size_in_bytes, bool range_sorted = false, double node_fill_factor = 0.75, double leaf_fill_factor = 0.6 ) : Impl(b, e, c_, node_cache_size_in_bytes, leaf_cache_size_in_bytes, range_sorted, node_fill_factor, leaf_fill_factor) { } void swap(map & obj) { std::swap(Impl, obj.Impl); } std::pair insert(const value_type & x) { return Impl.insert(x); } iterator insert(iterator pos, const value_type & x) { return Impl.insert(pos, x); } template void insert(InputIterator b, InputIterator e) { Impl.insert(b, e); } void erase(iterator pos) { Impl.erase(pos); } size_type erase(const key_type & k) { return Impl.erase(k); } void erase(iterator first, iterator last) { Impl.erase(first, last); } void clear() { Impl.clear(); } iterator find(const key_type & k) { return Impl.find(k); } const_iterator find(const key_type & k) const { return Impl.find(k); } size_type count(const key_type & k) { return Impl.count(k); } iterator lower_bound(const key_type & k) { return Impl.lower_bound(k); } const_iterator lower_bound(const key_type & k) const { return Impl.lower_bound(k); } iterator upper_bound(const key_type & k) { return Impl.upper_bound(k); } const_iterator upper_bound(const key_type & k) const { return Impl.upper_bound(k); } std::pair equal_range(const key_type & k) { return Impl.equal_range(k); } std::pair equal_range(const key_type & k) const { return Impl.equal_range(k); } data_type & operator [] (const key_type & k) { return Impl[k]; } //! \brief Enables leaf prefetching during scanning void enable_prefetching() { Impl.enable_prefetching(); } //! \brief Disables leaf prefetching during scanning void disable_prefetching() { Impl.disable_prefetching(); } //! \brief Returns the status of leaf prefetching during scanning bool prefetching_enabled() { return Impl.prefetching_enabled(); } //! \brief Prints cache statistics void print_statistics(std::ostream & o) const { Impl.print_statistics(o); } //! \brief Resets cache statistics void reset_statistics() { Impl.reset_statistics(); } ////////////////////////////////////////////////// template friend bool operator == (const map & a, const map & b); ////////////////////////////////////////////////// template friend bool operator < (const map & a, const map & b); ////////////////////////////////////////////////// template friend bool operator > (const map & a, const map & b); ////////////////////////////////////////////////// template friend bool operator != (const map & a, const map & b); ////////////////////////////////////////////////// template friend bool operator <= (const map & a, const map & b); ////////////////////////////////////////////////// template friend bool operator >= (const map & a, const map & b); ////////////////////////////////////////////////// }; template inline bool operator == (const map & a, const map & b) { return a.Impl == b.Impl; } template inline bool operator < (const map & a, const map & b) { return a.Impl < b.Impl; } template inline bool operator > (const map & a, const map & b) { return a.Impl > b.Impl; } template inline bool operator != (const map & a, const map & b) { return a.Impl != b.Impl; } template inline bool operator <= (const map & a, const map & b) { return a.Impl <= b.Impl; } template inline bool operator >= (const map & a, const map & b) { return a.Impl >= b.Impl; } //! \} __STXXL_END_NAMESPACE namespace std { template void swap(stxxl::map & a, stxxl::map & b ) { a.swap(b); } } #endif // !STXXL_MAP_HEADER stxxl-1.3.1/include/stxxl/bits/containers/pager.h0000644000175000017500000000625011535426670021710 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/containers/pager.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2002, 2003, 2006 Roman Dementiev * Copyright (C) 2011 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_PAGER_HEADER #define STXXL_PAGER_HEADER #include #include #include #include #include __STXXL_BEGIN_NAMESPACE //! \addtogroup stlcontinternals //! \{ enum pager_type { random, lru }; //! \brief Pager with \b random replacement strategy template class random_pager { random_number rnd; public: enum { n_pages = npages_ }; random_pager() { } int_type kick() { return rnd(npages_); } void hit(int_type ipage) { assert(ipage < int_type(npages_)); assert(ipage >= 0); } }; //! \brief Pager with \b LRU replacement strategy template class lru_pager : private noncopyable { typedef unsigned_type size_type; typedef std::list list_type; list_type history; simple_vector history_entry; public: enum { n_pages = npages_ }; lru_pager() : history_entry(n_pages) { for (size_type i = 0; i < n_pages; ++i) history_entry[i] = history.insert(history.end(), i); } size_type kick() { return history.back(); } void hit(size_type ipage) { assert(ipage < n_pages); history.splice(history.begin(), history, history_entry[ipage]); } void swap(lru_pager & obj) { history.swap(obj.history); history_entry.swap(obj.history_entry); } }; // specialization, size is specified at runtime template <> class lru_pager<0> : private noncopyable { typedef unsigned_type size_type; typedef std::list list_type; size_type n_pages; list_type history; simple_vector history_entry; public: lru_pager(size_type npages_ = 0) : n_pages(npages_), history_entry(n_pages) { for (size_type i = 0; i < n_pages; ++i) history_entry[i] = history.insert(history.end(), i); } size_type kick() { return history.back(); } void hit(size_type ipage) { assert(ipage < n_pages); history.splice(history.begin(), history, history_entry[ipage]); } void swap(lru_pager & obj) { std::swap(n_pages, obj.n_pages); history.swap(obj.history); history_entry.swap(obj.history_entry); } }; //! \} __STXXL_END_NAMESPACE namespace std { template void swap(stxxl::lru_pager & a, stxxl::lru_pager & b) { a.swap(b); } } #endif // !STXXL_PAGER_HEADER // vim: et:ts=4:sw=4 stxxl-1.3.1/include/stxxl/bits/containers/pq_ext_merger.h0000644000175000017500000012153111535151017023441 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/containers/pq_ext_merger.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 1999 Peter Sanders * Copyright (C) 2003, 2004, 2007 Roman Dementiev * Copyright (C) 2007-2009 Johannes Singler * Copyright (C) 2007-2010 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_PQ_EXT_MERGER_HEADER #define STXXL_PQ_EXT_MERGER_HEADER #include __STXXL_BEGIN_NAMESPACE //! \addtogroup stlcontinternals //! //! \{ /*! \internal */ namespace priority_queue_local { template class short_sequence : public std::pair { typedef std::pair pair; public: typedef Iterator iterator; typedef const iterator const_iterator; typedef typename std::iterator_traits::value_type value_type; typedef typename std::iterator_traits::difference_type size_type; typedef value_type & reference; typedef const value_type & const_reference; typedef unsigned_type origin_type; private: origin_type m_origin; public: short_sequence(Iterator first, Iterator last, origin_type origin) : pair(first, last), m_origin(origin) { } iterator begin() { return this->first; } const_iterator begin() const { return this->first; } const_iterator cbegin() const { return begin(); } iterator end() { return this->second; } const_iterator end() const { return this->second; } const_iterator cend() const { return end(); } reference front() { return *begin(); } const_reference front() const { return *begin(); } reference back() { return *(end() - 1); } const_reference back() const { return *(end() - 1); } size_type size() const { return end() - begin(); } bool empty() const { return size() == 0; } origin_type origin() const { return m_origin; } }; /** *! \brief External merger, based on the loser tree data structure. *! \param Arity_ maximum arity of merger, does not need to be a power of 2 */ template class ext_merger : private noncopyable { public: typedef stxxl::uint64 size_type; typedef BlockType_ block_type; typedef typename block_type::bid_type bid_type; typedef typename block_type::value_type value_type; typedef Cmp_ comparator_type; typedef AllocStr_ alloc_strategy; typedef read_write_pool pool_type; // arity_bound / 2 < arity <= arity_bound enum { arity = Arity_, arity_bound = 1UL << (LOG2::ceil) }; protected: comparator_type cmp; bool is_sentinel(const value_type & a) const { return !(cmp(cmp.min_value(), a)); // a <= cmp.min_value() } bool not_sentinel(const value_type & a) const { return cmp(cmp.min_value(), a); // a > cmp.min_value() } struct sequence_state : private noncopyable { block_type * block; //current block unsigned_type current; //current index in current block std::list * bids; //list of blocks forming this sequence comparator_type cmp; ext_merger * merger; bool allocated; //! \returns current element const value_type & operator * () const { return (*block)[current]; } sequence_state() : bids(NULL), allocated(false) { } ~sequence_state() { STXXL_VERBOSE2("ext_merger sequence_state::~sequence_state()"); if (bids != NULL) { block_manager * bm = block_manager::get_instance(); bm->delete_blocks(bids->begin(), bids->end()); delete bids; } } void make_inf() { current = 0; (*block)[0] = cmp.min_value(); } bool is_sentinel(const value_type & a) const { return !(cmp(cmp.min_value(), a)); } bool not_sentinel(const value_type & a) const { return cmp(cmp.min_value(), a); } void swap(sequence_state & obj) { if (&obj != this) { std::swap(current, obj.current); std::swap(block, obj.block); std::swap(bids, obj.bids); assert(merger == obj.merger); std::swap(allocated, obj.allocated); } } sequence_state & operator ++ () { assert(not_sentinel((*block)[current])); assert(current < block->size); ++current; if (current == block->size) { STXXL_VERBOSE2("ext_merger sequence_state operator++ crossing block border "); // go to the next block assert(bids != NULL); if (bids->empty()) // if there is no next block { STXXL_VERBOSE2("ext_merger sequence_state operator++ it was the last block in the sequence "); delete bids; bids = NULL; make_inf(); } else { STXXL_VERBOSE2("ext_merger sequence_state operator++ there is another block "); bid_type bid = bids->front(); bids->pop_front(); merger->pool->hint(bid); if (!(bids->empty())) { STXXL_VERBOSE2("ext_merger sequence_state operator++ more blocks exist in a sequence, hinting the next"); merger->pool->hint(bids->front()); } merger->pool->read(block, bid)->wait(); STXXL_VERBOSE2("first element of read block " << bid << " " << *(block->begin()) << " cached in " << block); if (!(bids->empty())) merger->pool->hint(bids->front()); // re-hint, reading might have made a block free block_manager::get_instance()->delete_block(bid); current = 0; } } return *this; } }; #if STXXL_PQ_EXTERNAL_LOSER_TREE struct Entry { value_type key; // key of loser element (winner for 0) unsigned_type index; // the number of the losing segment }; #endif //STXXL_PQ_EXTERNAL_LOSER_TREE size_type size_; // total number of elements stored unsigned_type log_k; // log of current tree size unsigned_type k; // invariant (k == 1 << log_k), always a power of 2 // only entries 0 .. arity-1 may hold actual sequences, the other // entries arity .. arity_bound-1 are sentinels to make the size of the tree // a power of 2 always // stack of empty segment indices internal_bounded_stack free_segments; #if STXXL_PQ_EXTERNAL_LOSER_TREE // upper levels of loser trees // entry[0] contains the winner info Entry entry[arity_bound]; #endif //STXXL_PQ_EXTERNAL_LOSER_TREE // leaf information // note that Knuth uses indices k..k-1 // while we use 0..k-1 sequence_state states[arity_bound]; // sequence including current position, dereference gives current element pool_type * pool; block_type * sentinel_block; public: ext_merger() : size_(0), log_k(0), k(1), pool(0) { init(); } ext_merger(pool_type * pool_) : size_(0), log_k(0), k(1), pool(pool_) { init(); } virtual ~ext_merger() { STXXL_VERBOSE1("ext_merger::~ext_merger()"); for (unsigned_type i = 0; i < arity; ++i) { delete states[i].block; } delete sentinel_block; } void set_pool(pool_type * pool_) { pool = pool_; } private: void init() { STXXL_VERBOSE2("ext_merger::init()"); assert(!cmp(cmp.min_value(), cmp.min_value())); // verify strict weak ordering sentinel_block = NULL; if (arity < arity_bound) { sentinel_block = new block_type; for (unsigned_type i = 0; i < block_type::size; ++i) (*sentinel_block)[i] = cmp.min_value(); if (arity + 1 == arity_bound) { // same memory consumption, but smaller merge width, better use arity = arity_bound STXXL_ERRMSG("inefficient PQ parameters for ext_merger: arity + 1 == arity_bound"); } } for (unsigned_type i = 0; i < arity_bound; ++i) { states[i].merger = this; if (i < arity) states[i].block = new block_type; else states[i].block = sentinel_block; states[i].make_inf(); } assert(k == 1); free_segments.push(0); //total state: one free sequence rebuild_loser_tree(); #if STXXL_PQ_EXTERNAL_LOSER_TREE assert(is_sentinel(*states[entry[0].index])); #endif //STXXL_PQ_EXTERNAL_LOSER_TREE } // rebuild loser tree information from the values in current void rebuild_loser_tree() { #if STXXL_PQ_EXTERNAL_LOSER_TREE unsigned_type winner = init_winner(1); entry[0].index = winner; entry[0].key = *(states[winner]); #endif //STXXL_PQ_EXTERNAL_LOSER_TREE } #if STXXL_PQ_EXTERNAL_LOSER_TREE // given any values in the leaves this // routing recomputes upper levels of the tree // from scratch in linear time // initialize entry[root].index and the subtree rooted there // return winner index unsigned_type init_winner(unsigned_type root) { if (root >= k) { // leaf reached return root - k; } else { unsigned_type left = init_winner(2 * root); unsigned_type right = init_winner(2 * root + 1); value_type lk = *(states[left]); value_type rk = *(states[right]); if (!(cmp(lk, rk))) { // right subtree looses entry[root].index = right; entry[root].key = rk; return left; } else { entry[root].index = left; entry[root].key = lk; return right; } } } // first go up the tree all the way to the root // hand down old winner for the respective subtree // based on new value, and old winner and loser // update each node on the path to the root top down. // This is implemented recursively void update_on_insert( unsigned_type node, const value_type & new_key, unsigned_type new_index, value_type * winner_key, unsigned_type * winner_index, // old winner unsigned_type * mask) // 1 << (ceil(log KNK) - dist-from-root) { if (node == 0) { // winner part of root *mask = 1 << (log_k - 1); *winner_key = entry[0].key; *winner_index = entry[0].index; if (cmp(entry[node].key, new_key)) { entry[node].key = new_key; entry[node].index = new_index; } } else { update_on_insert(node >> 1, new_key, new_index, winner_key, winner_index, mask); value_type loserKey = entry[node].key; unsigned_type loserIndex = entry[node].index; if ((*winner_index & *mask) != (new_index & *mask)) { // different subtrees if (cmp(loserKey, new_key)) { // new_key will have influence here if (cmp(*winner_key, new_key)) { // old winner loses here entry[node].key = *winner_key; entry[node].index = *winner_index; } else { // new entry looses here entry[node].key = new_key; entry[node].index = new_index; } } *winner_key = loserKey; *winner_index = loserIndex; } // note that nothing needs to be done if // the winner came from the same subtree // a) new_key <= winner_key => even more reason for the other tree to lose // b) new_key > winner_key => the old winner will beat the new // entry further down the tree // also the same old winner is handed down the tree *mask >>= 1; // next level } } #endif //STXXL_PQ_EXTERNAL_LOSER_TREE // make the tree two times as wide void double_k() { STXXL_VERBOSE1("ext_merger::double_k (before) k=" << k << " log_k=" << log_k << " arity_bound=" << arity_bound << " arity=" << arity << " #free=" << free_segments.size()); assert(k > 0); assert(k < arity); assert(free_segments.empty()); // stack was free (probably not needed) // make all new entries free // and push them on the free stack for (unsigned_type i = 2 * k - 1; i >= k; i--) //backwards { states[i].make_inf(); if (i < arity) free_segments.push(i); } // double the size k *= 2; log_k++; STXXL_VERBOSE1("ext_merger::double_k (after) k=" << k << " log_k=" << log_k << " arity_bound=" << arity_bound << " arity=" << arity << " #free=" << free_segments.size()); assert(!free_segments.empty()); // recompute loser tree information rebuild_loser_tree(); } // compact nonempty segments in the left half of the tree void compact_tree() { STXXL_VERBOSE1("ext_merger::compact_tree (before) k=" << k << " log_k=" << log_k << " #free=" << free_segments.size()); assert(log_k > 0); // compact all nonempty segments to the left unsigned_type target = 0; for (unsigned_type from = 0; from < k; from++) { if (!is_segment_empty(from)) { assert(is_segment_allocated(from)); if (from != target) { assert(!is_segment_allocated(target)); states[target].swap(states[from]); } ++target; } } // half degree as often as possible while (k > 1 && target <= (k / 2)) { k /= 2; log_k--; } // overwrite garbage and compact the stack of free segment indices free_segments.clear(); // none free for ( ; target < k; target++) { assert(!is_segment_allocated(target)); states[target].make_inf(); if (target < arity) free_segments.push(target); } STXXL_VERBOSE1("ext_merger::compact_tree (after) k=" << k << " log_k=" << log_k << " #free=" << free_segments.size()); assert(k > 0); // recompute loser tree information rebuild_loser_tree(); } #if 0 void swap(ext_merger & obj) { std::swap(cmp, obj.cmp); std::swap(free_segments, obj.free_segments); std::swap(size_, obj.size_); std::swap(log_k, obj.log_k); std::swap(k, obj.k); swap_1D_arrays(entry, obj.entry, arity_bound); swap_1D_arrays(states, obj.states, arity_bound); // std::swap(pool,obj.pool); } #endif public: unsigned_type mem_cons() const // only rough estimation { return (STXXL_MIN(arity + 1, arity_bound) * block_type::raw_size); } // delete the (length = end-begin) smallest elements and write them to [begin..end) // empty segments are deallocated // requires: // - there are at least length elements // - segments are ended by sentinels template void multi_merge(OutputIterator begin, OutputIterator end) { size_type length = end - begin; STXXL_VERBOSE1("ext_merger::multi_merge from " << k << " sequence(s), length = " << length); if (length == 0) return; assert(k > 0); assert(length <= size_); //This is the place to make statistics about external multi_merge calls. #if STXXL_PARALLEL && STXXL_PARALLEL_PQ_MULTIWAY_MERGE_EXTERNAL typedef stxxl::int64 diff_type; typedef std::pair sequence; std::vector seqs; std::vector orig_seq_index; Cmp_ cmp; priority_queue_local::invert_order inv_cmp(cmp); for (unsigned_type i = 0; i < k; ++i) //initialize sequences { if (states[i].current == states[i].block->size || is_sentinel(*states[i])) continue; seqs.push_back(std::make_pair(states[i].block->begin() + states[i].current, states[i].block->end())); orig_seq_index.push_back(i); #if STXXL_CHECK_ORDER_IN_SORTS if (!is_sentinel(*seqs.back().first) && !stxxl::is_sorted(seqs.back().first, seqs.back().second, inv_cmp)) { STXXL_VERBOSE1("length " << i << " " << (seqs.back().second - seqs.back().first)); for (value_type * v = seqs.back().first + 1; v < seqs.back().second; ++v) { if (inv_cmp(*v, *(v - 1))) { STXXL_VERBOSE1("Error at position " << i << "/" << (v - seqs.back().first - 1) << "/" << (v - seqs.back().first) << " " << *(v - 1) << " " << *v); } if (is_sentinel(*v)) { STXXL_VERBOSE1("Wrong sentinel at position " << (v - seqs.back().first)); } } assert(false); } #endif //Hint first non-internal (actually second) block of this sequence. if (states[i].bids != NULL && !states[i].bids->empty()) pool->hint(states[i].bids->front()); } assert(seqs.size() > 0); #if STXXL_CHECK_ORDER_IN_SORTS value_type last_elem; #endif diff_type rest = length; //elements still to merge for this output block while (rest > 0) { value_type min_last = cmp.min_value(); // minimum of the sequences' last elements diff_type total_size = 0; for (unsigned_type i = 0; i < seqs.size(); ++i) { diff_type seq_i_size = seqs[i].second - seqs[i].first; if (seq_i_size > 0) { total_size += seq_i_size; if (inv_cmp(*(seqs[i].second - 1), min_last)) min_last = *(seqs[i].second - 1); STXXL_VERBOSE1("front block of seq " << i << ": front=" << *(seqs[i].first) << " back=" << *(seqs[i].second - 1) << " len=" << seq_i_size); } else { STXXL_VERBOSE1("front block of seq " << i << ": empty"); } } assert(total_size > 0); assert(!is_sentinel(min_last)); STXXL_VERBOSE1("min_last " << min_last << " total size " << total_size << " num_seq " << seqs.size()); diff_type less_equal_than_min_last = 0; //locate this element in all sequences for (unsigned_type i = 0; i < seqs.size(); ++i) { //assert(seqs[i].first < seqs[i].second); typename block_type::iterator position = std::upper_bound(seqs[i].first, seqs[i].second, min_last, inv_cmp); //no element larger than min_last is merged STXXL_VERBOSE1("seq " << i << ": " << (position - seqs[i].first) << " greater equal than " << min_last); less_equal_than_min_last += (position - seqs[i].first); } diff_type output_size = STXXL_MIN(less_equal_than_min_last, rest); // at most rest elements STXXL_VERBOSE1("output_size=" << output_size << " = min(leq_t_ml=" << less_equal_than_min_last << ", rest=" << rest << ")"); assert(output_size > 0); //main call begin = parallel::multiway_merge(seqs.begin(), seqs.end(), begin, inv_cmp, output_size); //sequence iterators are progressed appropriately rest -= output_size; size_ -= output_size; for (unsigned_type i = 0; i < seqs.size(); ++i) { sequence_state & state = states[orig_seq_index[i]]; state.current = seqs[i].first - state.block->begin(); assert(seqs[i].first <= seqs[i].second); if (seqs[i].first == seqs[i].second) //has run empty { assert(state.current == state.block->size); if (state.bids == NULL || state.bids->empty()) // if there is no next block { STXXL_VERBOSE1("seq " << i << ": ext_merger::multi_merge(...) it was the last block in the sequence "); state.make_inf(); } else { #if STXXL_CHECK_ORDER_IN_SORTS last_elem = *(seqs[i].second - 1); #endif STXXL_VERBOSE1("seq " << i << ": ext_merger::multi_merge(...) there is another block "); bid_type bid = state.bids->front(); state.bids->pop_front(); pool->hint(bid); if (!(state.bids->empty())) { STXXL_VERBOSE2("seq " << i << ": ext_merger::multi_merge(...) more blocks exist, hinting the next"); pool->hint(state.bids->front()); } pool->read(state.block, bid)->wait(); STXXL_VERBOSE1("seq " << i << ": first element of read block " << bid << " " << *(state.block->begin()) << " cached in " << state.block); if (!(state.bids->empty())) pool->hint(state.bids->front()); // re-hint, reading might have made a block free state.current = 0; seqs[i] = std::make_pair(state.block->begin() + state.current, state.block->end()); block_manager::get_instance()->delete_block(bid); #if STXXL_CHECK_ORDER_IN_SORTS STXXL_VERBOSE1("before " << last_elem << " after " << *seqs[i].first << " newly loaded block " << bid); if (!stxxl::is_sorted(seqs[i].first, seqs[i].second, inv_cmp)) { STXXL_VERBOSE1("length " << i << " " << (seqs[i].second - seqs[i].first)); for (value_type * v = seqs[i].first + 1; v < seqs[i].second; ++v) { if (inv_cmp(*v, *(v - 1))) { STXXL_VERBOSE1("Error at position " << i << "/" << (v - seqs[i].first - 1) << "/" << (v - seqs[i].first) << " " << *(v - 1) << " " << *v); } if (is_sentinel(*v)) { STXXL_VERBOSE1("Wrong sentinel at position " << (v - seqs[i].first)); } } assert(false); } #endif } } } } //while (rest > 1) for (unsigned_type i = 0; i < seqs.size(); ++i) { unsigned_type seg = orig_seq_index[i]; if (is_segment_empty(seg)) { STXXL_VERBOSE1("deallocated " << seg); deallocate_segment(seg); } } #else // STXXL_PARALLEL && STXXL_PARALLEL_PQ_MULTIWAY_MERGE_EXTERNAL //Hint first non-internal (actually second) block of each sequence. for (unsigned_type i = 0; i < k; ++i) { if (states[i].bids != NULL && !states[i].bids->empty()) pool->hint(states[i].bids->front()); } switch (log_k) { case 0: assert(k == 1); assert(entry[0].index == 0); assert(free_segments.empty()); //memcpy(target, states[0], length * sizeof(value_type)); //std::copy(states[0],states[0]+length,target); for (size_type i = 0; i < length; ++i, ++(states[0]), ++begin) *begin = *(states[0]); entry[0].key = **states; if (is_segment_empty(0)) deallocate_segment(0); break; case 1: assert(k == 2); merge_iterator(states[0], states[1], begin, length, cmp); rebuild_loser_tree(); if (is_segment_empty(0) && is_segment_allocated(0)) deallocate_segment(0); if (is_segment_empty(1) && is_segment_allocated(1)) deallocate_segment(1); break; case 2: assert(k == 4); if (is_segment_empty(3)) merge3_iterator(states[0], states[1], states[2], begin, length, cmp); else merge4_iterator(states[0], states[1], states[2], states[3], begin, length, cmp); rebuild_loser_tree(); if (is_segment_empty(0) && is_segment_allocated(0)) deallocate_segment(0); if (is_segment_empty(1) && is_segment_allocated(1)) deallocate_segment(1); if (is_segment_empty(2) && is_segment_allocated(2)) deallocate_segment(2); if (is_segment_empty(3) && is_segment_allocated(3)) deallocate_segment(3); break; case 3: multi_merge_f(begin, end); break; case 4: multi_merge_f(begin, end); break; case 5: multi_merge_f(begin, end); break; case 6: multi_merge_f(begin, end); break; case 7: multi_merge_f(begin, end); break; case 8: multi_merge_f(begin, end); break; case 9: multi_merge_f(begin, end); break; case 10: multi_merge_f(begin, end); break; default: multi_merge_k(begin, end); break; } size_ -= length; #endif // compact tree if it got considerably smaller { const unsigned_type num_segments_used = std::min(arity, k) - free_segments.size(); const unsigned_type num_segments_trigger = k - (3 * k / 5); // using k/2 would be worst case inefficient (for large k) // for k \in {2, 4, 8} the trigger is k/2 which is good // because we have special mergers for k \in {1, 2, 4} // there is also a special 3-way-merger, that will be // triggered if k == 4 && is_segment_empty(3) STXXL_VERBOSE3("ext_merger compact? k=" << k << " #used=" << num_segments_used << " <= #trigger=" << num_segments_trigger << " ==> " << ((k > 1 && num_segments_used <= num_segments_trigger) ? "yes" : "no ") << " || " << ((k == 4 && !free_segments.empty() && !is_segment_empty(3)) ? "yes" : "no ") << " #free=" << free_segments.size()); if (k > 1 && ((num_segments_used <= num_segments_trigger) || (k == 4 && !free_segments.empty() && !is_segment_empty(3)))) { compact_tree(); } } } private: #if STXXL_PQ_EXTERNAL_LOSER_TREE // multi-merge for arbitrary K template void multi_merge_k(OutputIterator begin, OutputIterator end) { Entry * current_pos; value_type current_key; unsigned_type current_index; // leaf pointed to by current entry unsigned_type kReg = k; OutputIterator done = end; OutputIterator target = begin; unsigned_type winner_index = entry[0].index; value_type winner_key = entry[0].key; while (target != done) { // write result *target = *(states[winner_index]); // advance winner segment ++(states[winner_index]); winner_key = *(states[winner_index]); // remove winner segment if empty now if (is_sentinel(winner_key)) // deallocate_segment(winner_index); // go up the entry-tree for (unsigned_type i = (winner_index + kReg) >> 1; i > 0; i >>= 1) { current_pos = entry + i; current_key = current_pos->key; if (cmp(winner_key, current_key)) { current_index = current_pos->index; current_pos->key = winner_key; current_pos->index = winner_index; winner_key = current_key; winner_index = current_index; } } ++target; } entry[0].index = winner_index; entry[0].key = winner_key; } template void multi_merge_f(OutputIterator begin, OutputIterator end) { OutputIterator done = end; OutputIterator target = begin; unsigned_type winner_index = entry[0].index; Entry * reg_entry = entry; sequence_state * reg_states = states; value_type winner_key = entry[0].key; assert(log_k >= LogK); while (target != done) { // write result *target = *(reg_states[winner_index]); // advance winner segment ++(reg_states[winner_index]); winner_key = *(reg_states[winner_index]); // remove winner segment if empty now if (is_sentinel(winner_key)) deallocate_segment(winner_index); ++target; // update loser tree #define TreeStep(L) \ if (1 << LogK >= 1 << L) { \ Entry * pos ## L = reg_entry + ((winner_index + (1 << LogK)) >> (((int(LogK - L) + 1) >= 0) ? ((LogK - L) + 1) : 0)); \ value_type key ## L = pos ## L->key; \ if (cmp(winner_key, key ## L)) { \ unsigned_type index ## L = pos ## L->index; \ pos ## L->key = winner_key; \ pos ## L->index = winner_index; \ winner_key = key ## L; \ winner_index = index ## L; \ } \ } TreeStep(10); TreeStep(9); TreeStep(8); TreeStep(7); TreeStep(6); TreeStep(5); TreeStep(4); TreeStep(3); TreeStep(2); TreeStep(1); #undef TreeStep } reg_entry[0].index = winner_index; reg_entry[0].key = winner_key; } #endif //STXXL_PQ_EXTERNAL_LOSER_TREE public: bool is_space_available() const // for new segment { return k < arity || !free_segments.empty(); } // insert segment beginning at target // require: is_space_available() == 1 template void insert_segment(Merger & another_merger, size_type segment_size) { STXXL_VERBOSE1("ext_merger::insert_segment(merger,...)" << this); if (segment_size > 0) { // get a free slot if (free_segments.empty()) { // tree is too small double_k(); } assert(!free_segments.empty()); unsigned_type free_slot = free_segments.top(); free_segments.pop(); // link new segment assert(segment_size); unsigned_type nblocks = segment_size / block_type::size; //assert(nblocks); // at least one block STXXL_VERBOSE1("ext_merger::insert_segment nblocks=" << nblocks); if (nblocks == 0) { STXXL_VERBOSE1("ext_merger::insert_segment(merger,...) WARNING: inserting a segment with " << nblocks << " blocks"); STXXL_VERBOSE1("THIS IS INEFFICIENT: TRY TO CHANGE PRIORITY QUEUE PARAMETERS"); } unsigned_type first_size = segment_size % block_type::size; if (first_size == 0) { first_size = block_type::size; --nblocks; } block_manager * bm = block_manager::get_instance(); std::list * bids = new std::list(nblocks); bm->new_blocks(alloc_strategy(), bids->begin(), bids->end()); block_type * first_block = new block_type; another_merger.multi_merge( first_block->begin() + (block_type::size - first_size), first_block->end()); STXXL_VERBOSE1("last element of first block " << *(first_block->end() - 1)); assert(!cmp(*(first_block->begin() + (block_type::size - first_size)), *(first_block->end() - 1))); assert(pool->size_write() > 0); for (typename std::list::iterator curbid = bids->begin(); curbid != bids->end(); ++curbid) { block_type * b = pool->steal(); another_merger.multi_merge(b->begin(), b->end()); STXXL_VERBOSE1("first element of following block " << *curbid << " " << *(b->begin())); STXXL_VERBOSE1("last element of following block " << *curbid << " " << *(b->end() - 1)); assert(!cmp(*(b->begin()), *(b->end() - 1))); pool->write(b, *curbid); STXXL_VERBOSE1("written to block " << *curbid << " cached in " << b); } insert_segment(bids, first_block, first_size, free_slot); size_ += segment_size; #if STXXL_PQ_EXTERNAL_LOSER_TREE // propagate new information up the tree value_type dummyKey; unsigned_type dummyIndex; unsigned_type dummyMask; update_on_insert((free_slot + k) >> 1, *(states[free_slot]), free_slot, &dummyKey, &dummyIndex, &dummyMask); #endif //STXXL_PQ_EXTERNAL_LOSER_TREE } else { // deallocate memory ? STXXL_VERBOSE1("Merged segment with zero size."); } } size_type size() const { return size_; } protected: /*! \param bidlist list of blocks to insert \param first_block the first block of the sequence, before bidlist \param first_size number of elements in the first block \param slot slot to insert into */ void insert_segment(std::list * bidlist, block_type * first_block, unsigned_type first_size, unsigned_type slot) { STXXL_VERBOSE1("ext_merger::insert_segment(bidlist,...) " << this << " " << bidlist->size() << " " << slot); assert(!is_segment_allocated(slot)); assert(first_size > 0); sequence_state & new_sequence = states[slot]; new_sequence.current = block_type::size - first_size; std::swap(new_sequence.block, first_block); delete first_block; std::swap(new_sequence.bids, bidlist); if (bidlist) // the old list { assert(bidlist->empty()); delete bidlist; } new_sequence.allocated = true; assert(is_segment_allocated(slot)); } // free an empty segment . void deallocate_segment(unsigned_type slot) { STXXL_VERBOSE1("ext_merger::deallocate_segment() deleting segment " << slot << " allocated=" << int(is_segment_allocated(slot))); assert(is_segment_allocated(slot)); states[slot].allocated = false; states[slot].make_inf(); // push on the stack of free segment indices free_segments.push(slot); } // is this segment empty ? bool is_segment_empty(unsigned_type slot) const { return is_sentinel(*(states[slot])); } // Is this segment allocated? Otherwise it's empty, // already on the stack of free segment indices and can be reused. bool is_segment_allocated(unsigned_type slot) const { return states[slot].allocated; } }; // ext_merger } // priority_queue_local //! \} __STXXL_END_NAMESPACE #endif // !STXXL_PQ_EXT_MERGER_HEADER // vim: et:ts=4:sw=4 stxxl-1.3.1/include/stxxl/bits/containers/pq_helpers.h0000644000175000017500000001356011520237720022744 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/containers/pq_helpers.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 1999 Peter Sanders * Copyright (C) 2003, 2004, 2007 Roman Dementiev * Copyright (C) 2007, 2009 Johannes Singler * Copyright (C) 2007, 2008 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_PQ_HELPERS_HEADER #define STXXL_PQ_HELPERS_HEADER #include __STXXL_BEGIN_NAMESPACE //! \addtogroup stlcontinternals //! //! \{ /*! \internal */ namespace priority_queue_local { /** * @brief Similar to std::priority_queue, with the following differences: * - Maximum size is fixed at construction time, so an array can be used. * - Provides access to underlying heap, so (parallel) sorting in place is possible. * - Can be cleared "at once", without reallocation. */ template , typename _Compare = std::less > class internal_priority_queue { // concept requirements typedef typename _Sequence::value_type _Sequence_value_type; public: typedef typename _Sequence::value_type value_type; typedef typename _Sequence::reference reference; typedef typename _Sequence::const_reference const_reference; typedef typename _Sequence::size_type size_type; typedef _Sequence container_type; protected: // See queue::heap for notes on these names. _Sequence heap; _Compare comp; size_type current_size; public: /** * @brief Default constructor creates no elements. */ explicit internal_priority_queue(size_type capacity) : heap(capacity), current_size(0) { } /** * Returns true if the %queue is empty. */ bool empty() const { return current_size == 0; } /** Returns the number of elements in the %queue. */ size_type size() const { return current_size; } /** * Returns a read-only (constant) reference to the data at the first * element of the %queue. */ const_reference top() const { return heap.front(); } /** * @brief Add data to the %queue. * @param __x Data to be added. * * This is a typical %queue operation. * The time complexity of the operation depends on the underlying * sequence. */ void push(const value_type & __x) { heap[current_size] = __x; ++current_size; std::push_heap(heap.begin(), heap.begin() + current_size, comp); } /** * @brief Removes first element. * * This is a typical %queue operation. It shrinks the %queue * by one. The time complexity of the operation depends on the * underlying sequence. * * Note that no data is returned, and if the first element's * data is needed, it should be retrieved before pop() is * called. */ void pop() { std::pop_heap(heap.begin(), heap.begin() + current_size, comp); --current_size; } /** * @brief Sort all contained elements, write result to @c target. */ void sort_to(value_type * target) { potentially_parallel:: sort(heap.begin(), heap.begin() + current_size, comp); std::reverse_copy(heap.begin(), heap.begin() + current_size, target); } /** * @brief Remove all contained elements. */ void clear() { current_size = 0; } }; /** * @brief Inverts the order of a comparison functor by swapping its arguments. */ template class invert_order { protected: Predicate pred; public: explicit invert_order(const Predicate & _pred) : pred(_pred) { } bool operator () (const first_argument_type & x, const second_argument_type & y) const { return pred(y, x); } }; /** * \brief Similar to std::stack, with the following differences: * - Maximum size is fixed at compilation time, so an array can be used. * - Can be cleared "at once", without reallocation. */ template class internal_bounded_stack { typedef Tp_ value_type; typedef unsigned_type size_type; enum { max_size = max_size_ }; size_type size_; value_type array[max_size]; public: internal_bounded_stack() : size_(0) { } void push(const value_type & x) { assert(size_ < max_size); array[size_++] = x; } const value_type & top() const { assert(size_ > 0); return array[size_ - 1]; } void pop() { assert(size_ > 0); --size_; } void clear() { size_ = 0; } size_type size() const { return size_; } bool empty() const { return size_ == 0; } }; } //priority_queue_local //! \} __STXXL_END_NAMESPACE #endif // !STXXL_PQ_HELPERS_HEADER // vim: et:ts=4:sw=4 stxxl-1.3.1/include/stxxl/bits/containers/vector.h0000644000175000017500000014215511535500414022106 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/containers/vector.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2002-2008 Roman Dementiev * Copyright (C) 2007-2009 Johannes Singler * Copyright (C) 2008-2010 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_VECTOR_HEADER #define STXXL_VECTOR_HEADER #include #include #include #include #include #include #include #include #include #include __STXXL_BEGIN_NAMESPACE //! \weakgroup stlcont Containers //! \ingroup stllayer //! Containers with STL-compatible interface //! \weakgroup stlcontinternals Internals //! \ingroup stlcont //! \{ template class double_blocked_index { static const size_type modulo12 = modulo1 * modulo2; size_type pos, block1, block2, offset; //! \invariant block2 * modulo12 + block1 * modulo1 + offset == pos && 0 <= block1 < modulo2 && 0 <= offset < modulo1 void set(size_type pos) { this->pos = pos; block2 = pos / modulo12; pos -= block2 * modulo12; block1 = pos / modulo1; offset = (pos - block1 * modulo1); assert(block2 * modulo12 + block1 * modulo1 + offset == this->pos); assert(/* 0 <= block1 && */ block1 < modulo2); assert(/* 0 <= offset && */ offset < modulo1); } public: double_blocked_index() { set(0); } double_blocked_index(size_type pos) { set(pos); } double_blocked_index(size_type block2, size_type block1, size_type offset) { assert(/* 0 <= block1 && */ block1 < modulo2); assert(/* 0 <= offset && */ offset < modulo1); this->block2 = block2; this->block1 = block1; this->offset = offset; pos = block2 * modulo12 + block1 * modulo1 + offset; } double_blocked_index & operator = (size_type pos) { set(pos); return *this; } //pre-increment operator double_blocked_index & operator ++ () { ++pos; ++offset; if (offset == modulo1) { offset = 0; ++block1; if (block1 == modulo2) { block1 = 0; ++block2; } } assert(block2 * modulo12 + block1 * modulo1 + offset == this->pos); assert(/* 0 <= block1 && */ block1 < modulo2); assert(/* 0 <= offset && */ offset < modulo1); return *this; } //post-increment operator double_blocked_index operator ++ (int) { double_blocked_index former(*this); operator ++ (); return former; } //pre-increment operator double_blocked_index & operator -- () { --pos; if (offset == 0) { offset = modulo1; if (block1 == 0) { block1 = modulo2; --block2; } --block1; } --offset; assert(block2 * modulo12 + block1 * modulo1 + offset == this->pos); assert(/*0 <= block1 &&*/ block1 < modulo2); assert(/*0 <= offset &&*/ offset < modulo1); return *this; } //post-increment operator double_blocked_index operator -- (int) { double_blocked_index former(*this); operator -- (); return former; } double_blocked_index operator + (size_type addend) const { return double_blocked_index(pos + addend); } double_blocked_index & operator += (size_type addend) { set(pos + addend); return *this; } double_blocked_index operator - (size_type addend) const { return double_blocked_index(pos - addend); } size_type operator - (const double_blocked_index & dbi2) const { return pos - dbi2.pos; } double_blocked_index & operator -= (size_type subtrahend) { set(pos - subtrahend); return *this; } bool operator == (const double_blocked_index & dbi2) const { return pos == dbi2.pos; } bool operator != (const double_blocked_index & dbi2) const { return pos != dbi2.pos; } bool operator < (const double_blocked_index & dbi2) const { return pos < dbi2.pos; } bool operator <= (const double_blocked_index & dbi2) const { return pos <= dbi2.pos; } bool operator > (const double_blocked_index & dbi2) const { return pos > dbi2.pos; } bool operator >= (const double_blocked_index & dbi2) const { return pos >= dbi2.pos; } double_blocked_index & operator >>= (size_type shift) { set(pos >> shift); return *this; } size_type get_pos() const { return pos; } const size_type & get_block2() const { return block2; } const size_type & get_block1() const { return block1; } const size_type & get_offset() const { return offset; } }; template class bid_vector : public std::vector > { public: typedef std::vector > _Derived; typedef typename _Derived::size_type size_type; typedef typename _Derived::value_type bid_type; bid_vector(size_type _sz) : _Derived(_sz) { } }; template < typename Tp_, unsigned PgSz_, typename PgTp_, unsigned BlkSize_, typename AllocStr_, typename SzTp_> class vector; template class const_vector_iterator; //! \brief External vector iterator, model of \c ext_random_access_iterator concept template class vector_iterator { typedef vector_iterator _Self; typedef const_vector_iterator _CIterator; friend class const_vector_iterator; public: typedef _CIterator const_iterator; typedef _Self iterator; typedef unsigned block_offset_type; typedef vector vector_type; friend class vector; typedef typename vector_type::bids_container_type bids_container_type; typedef typename bids_container_type::iterator bids_container_iterator; typedef typename bids_container_type::bid_type bid_type; typedef typename vector_type::block_type block_type; typedef typename vector_type::blocked_index_type blocked_index_type; typedef std::random_access_iterator_tag iterator_category; typedef typename vector_type::size_type size_type; typedef typename vector_type::difference_type difference_type; typedef typename vector_type::value_type value_type; typedef typename vector_type::reference reference; typedef typename vector_type::const_reference const_reference; typedef typename vector_type::pointer pointer; typedef typename vector_type::const_pointer const_pointer; protected: blocked_index_type offset; vector_type * p_vector; private: vector_iterator(vector_type * v, size_type o) : offset(o), p_vector(v) { } public: vector_iterator() : offset(0), p_vector(NULL) { } vector_iterator(const _Self & a) : offset(a.offset), p_vector(a.p_vector) { } block_offset_type block_offset() const { return static_cast(offset.get_offset()); } bids_container_iterator bid() const { return p_vector->bid(offset); } difference_type operator - (const _Self & a) const { return offset - a.offset; } difference_type operator - (const const_iterator & a) const { return offset - a.offset; } _Self operator - (size_type op) const { return _Self(p_vector, offset.get_pos() - op); } _Self operator + (size_type op) const { return _Self(p_vector, offset.get_pos() + op); } _Self & operator -= (size_type op) { offset -= op; return *this; } _Self & operator += (size_type op) { offset += op; return *this; } reference operator * () { return p_vector->element(offset); } pointer operator -> () { return &(p_vector->element(offset)); } const_reference operator * () const { return p_vector->const_element(offset); } const_pointer operator -> () const { return &(p_vector->const_element(offset)); } reference operator [] (size_type op) { return p_vector->element(offset.get_pos() + op); } const_reference operator [] (size_type op) const { return p_vector->const_element(offset.get_pos() + op); } void block_externally_updated() { p_vector->block_externally_updated(offset); } _STXXL_DEPRECATED(void touch()) { block_externally_updated(); } _Self & operator ++ () { offset++; return *this; } _Self operator ++ (int) { _Self __tmp = *this; offset++; return __tmp; } _Self & operator -- () { offset--; return *this; } _Self operator -- (int) { _Self __tmp = *this; offset--; return __tmp; } bool operator == (const _Self & a) const { assert(p_vector == a.p_vector); return offset == a.offset; } bool operator != (const _Self & a) const { assert(p_vector == a.p_vector); return offset != a.offset; } bool operator < (const _Self & a) const { assert(p_vector == a.p_vector); return offset < a.offset; } bool operator <= (const _Self & a) const { assert(p_vector == a.p_vector); return offset <= a.offset; } bool operator > (const _Self & a) const { assert(p_vector == a.p_vector); return offset > a.offset; } bool operator >= (const _Self & a) const { assert(p_vector == a.p_vector); return offset >= a.offset; } bool operator == (const const_iterator & a) const { assert(p_vector == a.p_vector); return offset == a.offset; } bool operator != (const const_iterator & a) const { assert(p_vector == a.p_vector); return offset != a.offset; } bool operator < (const const_iterator & a) const { assert(p_vector == a.p_vector); return offset < a.offset; } bool operator <= (const const_iterator & a) const { assert(p_vector == a.p_vector); return offset <= a.offset; } bool operator > (const const_iterator & a) const { assert(p_vector == a.p_vector); return offset > a.offset; } bool operator >= (const const_iterator & a) const { assert(p_vector == a.p_vector); return offset >= a.offset; } void flush() { p_vector->flush(); } #if 0 std::ostream & operator << (std::ostream & o) const { o << "vectorpointer: " << ((void *)p_vector) << " offset: " << offset; return o; } #endif }; //! \brief Const external vector iterator, model of \c ext_random_access_iterator concept template class const_vector_iterator { typedef const_vector_iterator _Self; typedef vector_iterator _NonConstIterator; friend class vector_iterator; public: typedef _Self const_iterator; typedef _NonConstIterator iterator; typedef unsigned block_offset_type; typedef vector vector_type; friend class vector; typedef typename vector_type::bids_container_type bids_container_type; typedef typename bids_container_type::iterator bids_container_iterator; typedef typename bids_container_type::bid_type bid_type; typedef typename vector_type::block_type block_type; typedef typename vector_type::blocked_index_type blocked_index_type; typedef std::random_access_iterator_tag iterator_category; typedef typename vector_type::size_type size_type; typedef typename vector_type::difference_type difference_type; typedef typename vector_type::value_type value_type; typedef typename vector_type::const_reference reference; typedef typename vector_type::const_reference const_reference; typedef typename vector_type::const_pointer pointer; typedef typename vector_type::const_pointer const_pointer; protected: blocked_index_type offset; const vector_type * p_vector; private: const_vector_iterator(const vector_type * v, size_type o) : offset(o), p_vector(v) { } public: const_vector_iterator() : offset(0), p_vector(NULL) { } const_vector_iterator(const _Self & a) : offset(a.offset), p_vector(a.p_vector) { } const_vector_iterator(const iterator & a) : offset(a.offset), p_vector(a.p_vector) { } block_offset_type block_offset() const { return static_cast(offset.get_offset()); } bids_container_iterator bid() const { return ((vector_type *)p_vector)->bid(offset); } difference_type operator - (const _Self & a) const { return offset - a.offset; } difference_type operator - (const iterator & a) const { return offset - a.offset; } _Self operator - (size_type op) const { return _Self(p_vector, offset.get_pos() - op); } _Self operator + (size_type op) const { return _Self(p_vector, offset.get_pos() + op); } _Self & operator -= (size_type op) { offset -= op; return *this; } _Self & operator += (size_type op) { offset += op; return *this; } const_reference operator * () const { return p_vector->const_element(offset); } const_pointer operator -> () const { return &(p_vector->const_element(offset)); } const_reference operator [] (size_type op) const { return p_vector->const_element(offset.get_pos() + op); } void block_externally_updated() { p_vector->block_externally_updated(offset); } _STXXL_DEPRECATED(void touch()) { block_externally_updated(); } _Self & operator ++ () { offset++; return *this; } _Self operator ++ (int) { _Self tmp_ = *this; offset++; return tmp_; } _Self & operator -- () { offset--; return *this; } _Self operator -- (int) { _Self __tmp = *this; offset--; return __tmp; } bool operator == (const _Self & a) const { assert(p_vector == a.p_vector); return offset == a.offset; // or (offset + stxxl::int64(p_vector)) } bool operator != (const _Self & a) const { assert(p_vector == a.p_vector); return offset != a.offset; } bool operator < (const _Self & a) const { assert(p_vector == a.p_vector); return offset < a.offset; } bool operator <= (const _Self & a) const { assert(p_vector == a.p_vector); return offset <= a.offset; } bool operator > (const _Self & a) const { assert(p_vector == a.p_vector); return offset > a.offset; } bool operator >= (const _Self & a) const { assert(p_vector == a.p_vector); return offset >= a.offset; } bool operator == (const iterator & a) const { assert(p_vector == a.p_vector); return offset == a.offset; // or (offset + stxxl::int64(p_vector)) } bool operator != (const iterator & a) const { assert(p_vector == a.p_vector); return offset != a.offset; } bool operator < (const iterator & a) const { assert(p_vector == a.p_vector); return offset < a.offset; } bool operator <= (const iterator & a) const { assert(p_vector == a.p_vector); return offset <= a.offset; } bool operator > (const iterator & a) const { assert(p_vector == a.p_vector); return offset > a.offset; } bool operator >= (const iterator & a) const { assert(p_vector == a.p_vector); return offset >= a.offset; } void flush() { p_vector->flush(); } #if 0 std::ostream & operator << (std::ostream & o) const { o << "vector pointer: " << ((void *)p_vector) << " offset: " << offset; return o; } #endif }; //! \brief External vector container //! For semantics of the methods see documentation of the STL std::vector //! \tparam Tp_ type of contained objects (POD with no references to internal memory) //! \tparam PgSz_ number of blocks in a page //! \tparam PgTp_ pager type, \c random_pager or \c lru_pager, where x is number of pages, //! default is \c lru_pager<8> //! \tparam BlkSize_ external block size in bytes, default is 2 MiB //! \tparam AllocStr_ one of allocation strategies: \c striping , \c RC , \c SR , or \c FR //! default is RC //! //! Memory consumption: BlkSize_*x*PgSz_ bytes //! \warning Do not store references to the elements of an external vector. Such references //! might be invalidated during any following access to elements of the vector template < typename Tp_, unsigned PgSz_ = 4, typename PgTp_ = lru_pager<8>, unsigned BlkSize_ = STXXL_DEFAULT_BLOCK_SIZE(Tp_), typename AllocStr_ = STXXL_DEFAULT_ALLOC_STRATEGY, typename SzTp_ = stxxl::uint64 // will be deprecated soon > class vector { public: typedef Tp_ value_type; typedef value_type & reference; typedef const value_type & const_reference; typedef value_type * pointer; typedef SzTp_ size_type; typedef stxxl::int64 difference_type; typedef const value_type * const_pointer; typedef PgTp_ pager_type; typedef AllocStr_ alloc_strategy_type; enum constants { block_size = BlkSize_, page_size = PgSz_, n_pages = pager_type::n_pages, on_disk = -1 }; typedef vector_iterator iterator; friend class vector_iterator; typedef const_vector_iterator const_iterator; friend class const_vector_iterator; typedef std::reverse_iterator reverse_iterator; typedef std::reverse_iterator const_reverse_iterator; typedef bid_vector bids_container_type; typedef typename bids_container_type::iterator bids_container_iterator; typedef typename bids_container_type::const_iterator const_bids_container_iterator; typedef typed_block block_type; typedef double_blocked_index blocked_index_type; private: alloc_strategy_type alloc_strategy; size_type _size; bids_container_type _bids; mutable pager_type pager; enum { valid_on_disk = 0, uninitialized = 1, dirty = 2 }; mutable std::vector _page_status; mutable std::vector _page_to_slot; mutable simple_vector _slot_to_page; mutable std::queue _free_slots; mutable simple_vector * _cache; file * _from; block_manager * bm; config * cfg; bool exported; size_type size_from_file_length(stxxl::uint64 file_length) const { stxxl::uint64 blocks_fit = file_length / stxxl::uint64(block_type::raw_size); size_type cur_size = blocks_fit * stxxl::uint64(block_type::size); stxxl::uint64 rest = file_length - blocks_fit * stxxl::uint64(block_type::raw_size); return (cur_size + rest / stxxl::uint64(sizeof(value_type))); } stxxl::uint64 file_length() const { typedef stxxl::uint64 file_size_type; size_type cur_size = size(); size_type num_full_blocks = cur_size / block_type::size; if (cur_size % block_type::size != 0) { size_type rest = cur_size - num_full_blocks * block_type::size; return file_size_type(num_full_blocks) * block_type::raw_size + rest * sizeof(value_type); } return file_size_type(num_full_blocks) * block_type::raw_size; } public: vector(size_type n = 0) : _size(n), _bids(div_ceil(n, block_type::size)), _page_status(div_ceil(_bids.size(), page_size)), _page_to_slot(div_ceil(_bids.size(), page_size)), _slot_to_page(n_pages), _cache(NULL), _from(NULL), exported(false) { bm = block_manager::get_instance(); cfg = config::get_instance(); allocate_page_cache(); int_type all_pages = div_ceil(_bids.size(), page_size); int_type i = 0; for ( ; i < all_pages; ++i) { _page_status[i] = uninitialized; _page_to_slot[i] = on_disk; } for (i = 0; i < n_pages; ++i) _free_slots.push(i); bm->new_blocks(alloc_strategy, _bids.begin(), _bids.end(), 0); } void swap(vector & obj) { std::swap(alloc_strategy, obj.alloc_strategy); std::swap(_size, obj._size); std::swap(_bids, obj._bids); std::swap(pager, obj.pager); std::swap(_page_status, obj._page_status); std::swap(_page_to_slot, obj._page_to_slot); std::swap(_slot_to_page, obj._slot_to_page); std::swap(_free_slots, obj._free_slots); std::swap(_cache, obj._cache); std::swap(_from, obj._from); std::swap(exported, obj.exported); } void allocate_page_cache() const { if (!_cache) _cache = new simple_vector(n_pages * page_size); } // allows to free the cache, but you may not access any element until call allocate_pacge_cache() again void deallocate_page_cache() const { flush(); delete _cache; _cache = NULL; } size_type capacity() const { return size_type(_bids.size()) * block_type::size; } //! \brief Returns the number of bytes that the vector has allocated on disks size_type raw_capacity() const { return size_type(_bids.size()) * block_type::raw_size; } void reserve(size_type n) { if (n <= capacity()) return; unsigned_type old_bids_size = _bids.size(); unsigned_type new_bids_size = div_ceil(n, block_type::size); unsigned_type new_pages = div_ceil(new_bids_size, page_size); _page_status.resize(new_pages, uninitialized); _page_to_slot.resize(new_pages, on_disk); _bids.resize(new_bids_size); if (_from == NULL) { bm->new_blocks(alloc_strategy, _bids.begin() + old_bids_size, _bids.end(), old_bids_size); } else { size_type offset = size_type(old_bids_size) * size_type(block_type::raw_size); bids_container_iterator it = _bids.begin() + old_bids_size; for ( ; it != _bids.end(); ++it, offset += size_type(block_type::raw_size)) { (*it).storage = _from; (*it).offset = offset; } STXXL_VERBOSE1("vector::reserve(): Changing size of file " << ((void *)_from) << " to " << offset); _from->set_size(offset); } } void resize(size_type n) { _resize(n); } void resize(size_type n, bool shrink_capacity) { if (shrink_capacity) _resize_shrink_capacity(n); else _resize(n); } private: void _resize(size_type n) { reserve(n); if (n < _size) { // mark excess pages as uninitialized and evict them from cache unsigned_type first_page_to_evict = div_ceil(n, block_type::size * page_size); for (unsigned_type i = first_page_to_evict; i < _page_status.size(); ++i) { if (_page_to_slot[i] != on_disk) { _free_slots.push(_page_to_slot[i]); _page_to_slot[i] = on_disk; } _page_status[i] = uninitialized; } } _size = n; } void _resize_shrink_capacity(size_type n) { unsigned_type old_bids_size = _bids.size(); unsigned_type new_bids_size = div_ceil(n, block_type::size); if (new_bids_size > old_bids_size) { reserve(n); } else if (new_bids_size < old_bids_size) { if (_from != NULL) _from->set_size(new_bids_size * block_type::raw_size); else bm->delete_blocks(_bids.begin() + old_bids_size, _bids.end()); _bids.resize(new_bids_size); unsigned_type new_pages = div_ceil(new_bids_size, page_size); _page_status.resize(new_pages); unsigned_type first_page_to_evict = div_ceil(new_bids_size, page_size); // clear dirty flag, so these pages will be never written std::fill(_page_status.begin() + first_page_to_evict, _page_status.end(), (unsigned char)valid_on_disk); } _size = n; } public: void clear() { _size = 0; if (_from == NULL) bm->delete_blocks(_bids.begin(), _bids.end()); _bids.clear(); _page_status.clear(); _page_to_slot.clear(); while (!_free_slots.empty()) _free_slots.pop(); for (int_type i = 0; i < n_pages; ++i) _free_slots.push(i); } void push_back(const_reference obj) { size_type old_size = _size; resize(old_size + 1); element(old_size) = obj; } void pop_back() { resize(_size - 1); } reference back() { return element(_size - 1); } reference front() { return element(0); } const_reference back() const { return const_element(_size - 1); } const_reference front() const { return const_element(0); } //! \brief Construct vector from a file //! \param from file to be constructed from //! \warning Only one \c vector can be assigned to a particular (physical) file. //! The block size of the vector must be a multiple of the element size //! \c sizeof(Tp_) and the page size (4096). vector(file * from, size_type size = size_type(-1)) : _size((size == size_type(-1)) ? size_from_file_length(from->size()) : size), _bids(div_ceil(_size, size_type(block_type::size))), _page_status(div_ceil(_bids.size(), page_size)), _page_to_slot(div_ceil(_bids.size(), page_size)), _slot_to_page(n_pages), _cache(NULL), _from(from), exported(false) { // initialize from file if (!block_type::has_only_data) { std::ostringstream str_; str_ << "The block size for a vector that is mapped to a file must be a multiple of the element size (" << sizeof(value_type) << ") and the page size (4096)."; throw std::runtime_error(str_.str()); } bm = block_manager::get_instance(); cfg = config::get_instance(); allocate_page_cache(); int_type all_pages = div_ceil(_bids.size(), page_size); int_type i = 0; for ( ; i < all_pages; ++i) { _page_status[i] = valid_on_disk; _page_to_slot[i] = on_disk; } for (i = 0; i < n_pages; ++i) _free_slots.push(i); //allocate blocks equidistantly and in-order size_type offset = 0; bids_container_iterator it = _bids.begin(); for ( ; it != _bids.end(); ++it, offset += size_type(block_type::raw_size)) { (*it).storage = from; (*it).offset = offset; } from->set_size(offset); } vector(const vector & obj) : _size(obj.size()), _bids(div_ceil(obj.size(), block_type::size)), _page_status(div_ceil(_bids.size(), page_size)), _page_to_slot(div_ceil(_bids.size(), page_size)), _slot_to_page(n_pages), _cache(NULL), _from(NULL), exported(false) { assert(!obj.exported); bm = block_manager::get_instance(); cfg = config::get_instance(); allocate_page_cache(); int_type all_pages = div_ceil(_bids.size(), page_size); int_type i = 0; for ( ; i < all_pages; ++i) { _page_status[i] = uninitialized; _page_to_slot[i] = on_disk; } for (i = 0; i < n_pages; ++i) _free_slots.push(i); bm->new_blocks(alloc_strategy, _bids.begin(), _bids.end(), 0); const_iterator inbegin = obj.begin(); const_iterator inend = obj.end(); std::copy(inbegin, inend, begin()); } vector & operator = (const vector & obj) { if (&obj != this) { vector tmp(obj); this->swap(tmp); } return *this; } size_type size() const { return _size; } bool empty() const { return (!_size); } iterator begin() { return iterator(this, 0); } const_iterator begin() const { return const_iterator(this, 0); } const_iterator cbegin() const { return begin(); } iterator end() { return iterator(this, _size); } const_iterator end() const { return const_iterator(this, _size); } const_iterator cend() const { return end(); } reverse_iterator rbegin() { return reverse_iterator(end()); } const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); } const_reverse_iterator crbegin() const { return const_reverse_iterator(end()); } reverse_iterator rend() { return reverse_iterator(begin()); } const_reverse_iterator rend() const { return const_reverse_iterator(begin()); } const_reverse_iterator crend() const { return const_reverse_iterator(begin()); } reference operator [] (size_type offset) { return element(offset); } const_reference operator [] (size_type offset) const { return const_element(offset); } bool is_element_cached(size_type offset) const { return is_page_cached(blocked_index_type(offset)); } void flush() const { simple_vector non_free_slots(n_pages); int_type i = 0; for ( ; i < n_pages; i++) non_free_slots[i] = true; while (!_free_slots.empty()) { non_free_slots[_free_slots.front()] = false; _free_slots.pop(); } for (i = 0; i < n_pages; i++) { _free_slots.push(i); int_type page_no = _slot_to_page[i]; if (non_free_slots[i]) { STXXL_VERBOSE1("vector: flushing page " << i << " at address " << (int64(page_no) * int64(block_type::size) * int64(page_size))); write_page(page_no, i); _page_to_slot[page_no] = on_disk; } } } ~vector() { STXXL_VERBOSE("~vector()"); try { flush(); } catch (io_error e) { STXXL_ERRMSG("io_error thrown in ~vector(): " << e.what()); } catch (...) { STXXL_ERRMSG("Exception thrown in ~vector()"); } if (!exported) { if (_from == NULL) bm->delete_blocks(_bids.begin(), _bids.end()); else // file must be truncated { STXXL_VERBOSE1("~vector(): Changing size of file " << ((void *)_from) << " to " << file_length()); STXXL_VERBOSE1("~vector(): size of the vector is " << size()); try { _from->set_size(file_length()); } catch (...) { STXXL_ERRMSG("Exception thrown in ~vector()...set_size()"); } } } delete _cache; } //! \brief Export data such that it is persistent on the file system. //! Resulting files will be numbered ascending. void export_files(std::string filename_prefix) { int64 no = 0; for (bids_container_iterator i = _bids.begin(); i != _bids.end(); ++i) { std::ostringstream number; number << std::setw(9) << std::setfill('0') << no; size_type current_block_size = ((i + 1) == _bids.end() && _size % block_type::size > 0) ? (_size % block_type::size) * sizeof(value_type) : block_type::size * sizeof(value_type); (*i).storage->export_files((*i).offset, current_block_size, filename_prefix + number.str()); ++no; } exported = true; } //! \brief Get the file associated with this vector, or NULL. file * get_file() const { return _from; } //! \brief Set the blocks and the size of this container explicitly. //! The vector must be completely empty before. template void set_content(const ForwardIterator & bid_begin, const ForwardIterator & bid_end, size_type n) { unsigned_type new_bids_size = div_ceil(n, block_type::size); _bids.resize(new_bids_size); std::copy(bid_begin, bid_end, _bids.begin()); unsigned_type new_pages = div_ceil(new_bids_size, page_size); _page_status.resize(new_pages, valid_on_disk); _page_to_slot.resize(new_pages, on_disk); _size = n; } private: bids_container_iterator bid(const size_type & offset) { return (_bids.begin() + static_cast (offset / block_type::size)); } bids_container_iterator bid(const blocked_index_type & offset) { return (_bids.begin() + static_cast (offset.get_block2() * PgSz_ + offset.get_block1())); } const_bids_container_iterator bid(const size_type & offset) const { return (_bids.begin() + static_cast (offset / block_type::size)); } const_bids_container_iterator bid(const blocked_index_type & offset) const { return (_bids.begin() + static_cast (offset.get_block2() * PgSz_ + offset.get_block1())); } void read_page(int_type page_no, int_type cache_slot) const { if (_page_status[page_no] == uninitialized) return; STXXL_VERBOSE1("vector " << this << ": reading page_no=" << page_no << " cache_slot=" << cache_slot); request_ptr * reqs = new request_ptr[page_size]; int_type block_no = page_no * page_size; int_type last_block = STXXL_MIN(block_no + page_size, int_type(_bids.size())); int_type i = cache_slot * page_size, j = 0; for ( ; block_no < last_block; ++block_no, ++i, ++j) { reqs[j] = (*_cache)[i].read(_bids[block_no]); } assert(last_block - page_no * page_size > 0); wait_all(reqs, last_block - page_no * page_size); delete[] reqs; } void write_page(int_type page_no, int_type cache_slot) const { if (!(_page_status[page_no] & dirty)) return; STXXL_VERBOSE1("vector " << this << ": writing page_no=" << page_no << " cache_slot=" << cache_slot); request_ptr * reqs = new request_ptr[page_size]; int_type block_no = page_no * page_size; int_type last_block = STXXL_MIN(block_no + page_size, int_type(_bids.size())); int_type i = cache_slot * page_size, j = 0; for ( ; block_no < last_block; ++block_no, ++i, ++j) { reqs[j] = (*_cache)[i].write(_bids[block_no]); } _page_status[page_no] = valid_on_disk; assert(last_block - page_no * page_size > 0); wait_all(reqs, last_block - page_no * page_size); delete[] reqs; } reference element(size_type offset) { #ifdef STXXL_RANGE_CHECK assert(offset < size()); #endif return element(blocked_index_type(offset)); } reference element(const blocked_index_type & offset) { #ifdef STXXL_RANGE_CHECK assert(offset.get_pos() < size()); #endif int_type page_no = offset.get_block2(); assert(page_no < int_type(_page_to_slot.size())); // fails if offset is too large, out of bound access int_type cache_slot = _page_to_slot[page_no]; if (cache_slot < 0) // == on_disk { if (_free_slots.empty()) // has to kick { int_type kicked_slot = pager.kick(); pager.hit(kicked_slot); int_type old_page_no = _slot_to_page[kicked_slot]; _page_to_slot[page_no] = kicked_slot; _page_to_slot[old_page_no] = on_disk; _slot_to_page[kicked_slot] = page_no; write_page(old_page_no, kicked_slot); read_page(page_no, kicked_slot); _page_status[page_no] = dirty; return (*_cache)[kicked_slot * page_size + offset.get_block1()][offset.get_offset()]; } else { int_type free_slot = _free_slots.front(); _free_slots.pop(); pager.hit(free_slot); _page_to_slot[page_no] = free_slot; _slot_to_page[free_slot] = page_no; read_page(page_no, free_slot); _page_status[page_no] = dirty; return (*_cache)[free_slot * page_size + offset.get_block1()][offset.get_offset()]; } } else { _page_status[page_no] = dirty; pager.hit(cache_slot); return (*_cache)[cache_slot * page_size + offset.get_block1()][offset.get_offset()]; } } // don't forget to first flush() the vector's cache before updating pages externally void page_externally_updated(unsigned_type page_no) const { // fails if offset is too large, out of bound access assert(page_no < _page_status.size()); // "A dirty page has been marked as newly initialized. The page content will be lost." assert(!(_page_status[page_no] & dirty)); if (_page_to_slot[page_no] != on_disk) { // remove page from cache _free_slots.push(_page_to_slot[page_no]); _page_to_slot[page_no] = on_disk; } _page_status[page_no] = valid_on_disk; } void block_externally_updated(size_type offset) const { page_externally_updated(offset / (block_type::size * page_size)); } void block_externally_updated(const blocked_index_type & offset) const { page_externally_updated(offset.get_block2()); } _STXXL_DEPRECATED(void touch(size_type offset) const) { page_externally_updated(offset / (block_type::size * page_size)); } _STXXL_DEPRECATED(void touch(const blocked_index_type & offset) const) { page_externally_updated(offset.get_block2()); } const_reference const_element(size_type offset) const { return const_element(blocked_index_type(offset)); } const_reference const_element(const blocked_index_type & offset) const { int_type page_no = offset.get_block2(); assert(page_no < int_type(_page_to_slot.size())); // fails if offset is too large, out of bound access int_type cache_slot = _page_to_slot[page_no]; if (cache_slot < 0) // == on_disk { if (_free_slots.empty()) // has to kick { int_type kicked_slot = pager.kick(); pager.hit(kicked_slot); int_type old_page_no = _slot_to_page[kicked_slot]; _page_to_slot[page_no] = kicked_slot; _page_to_slot[old_page_no] = on_disk; _slot_to_page[kicked_slot] = page_no; write_page(old_page_no, kicked_slot); read_page(page_no, kicked_slot); return (*_cache)[kicked_slot * page_size + offset.get_block1()][offset.get_offset()]; } else { int_type free_slot = _free_slots.front(); _free_slots.pop(); pager.hit(free_slot); _page_to_slot[page_no] = free_slot; _slot_to_page[free_slot] = page_no; read_page(page_no, free_slot); return (*_cache)[free_slot * page_size + offset.get_block1()][offset.get_offset()]; } } else { pager.hit(cache_slot); return (*_cache)[cache_slot * page_size + offset.get_block1()][offset.get_offset()]; } } bool is_page_cached(const blocked_index_type & offset) const { int_type page_no = offset.get_block2(); assert(page_no < int_type(_page_to_slot.size())); // fails if offset is too large, out of bound access int_type cache_slot = _page_to_slot[page_no]; return (cache_slot >= 0); // on_disk == -1 } }; template < typename Tp_, unsigned PgSz_, typename PgTp_, unsigned BlkSize_, typename AllocStr_, typename SzTp_> inline bool operator == (stxxl::vector & a, stxxl::vector & b) { return a.size() == b.size() && std::equal(a.begin(), a.end(), b.begin()); } template < typename Tp_, unsigned PgSz_, typename PgTp_, unsigned BlkSize_, typename AllocStr_, typename SzTp_> inline bool operator != (stxxl::vector & a, stxxl::vector & b) { return !(a == b); } template < typename Tp_, unsigned PgSz_, typename PgTp_, unsigned BlkSize_, typename AllocStr_, typename SzTp_> inline bool operator < (stxxl::vector & a, stxxl::vector & b) { return std::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end()); } template < typename Tp_, unsigned PgSz_, typename PgTp_, unsigned BlkSize_, typename AllocStr_, typename SzTp_> inline bool operator > (stxxl::vector & a, stxxl::vector & b) { return b < a; } template < typename Tp_, unsigned PgSz_, typename PgTp_, unsigned BlkSize_, typename AllocStr_, typename SzTp_> inline bool operator <= (stxxl::vector & a, stxxl::vector & b) { return !(b < a); } template < typename Tp_, unsigned PgSz_, typename PgTp_, unsigned BlkSize_, typename AllocStr_, typename SzTp_> inline bool operator >= (stxxl::vector & a, stxxl::vector & b) { return !(a < b); } //! \} //////////////////////////////////////////////////////////////////////////// // specialization for stxxl::vector, to use only const_iterators template bool is_sorted( stxxl::vector_iterator __first, stxxl::vector_iterator __last) { return is_sorted_helper( stxxl::const_vector_iterator(__first), stxxl::const_vector_iterator(__last)); } template bool is_sorted( stxxl::vector_iterator __first, stxxl::vector_iterator __last, _StrictWeakOrdering __comp) { return is_sorted_helper( stxxl::const_vector_iterator(__first), stxxl::const_vector_iterator(__last), __comp); } //////////////////////////////////////////////////////////////////////////// //! \addtogroup stlcont //! \{ //! \brief External vector type generator //! \tparam Tp_ type of contained objects (POD with no references to internal memory) //! \tparam PgSz_ number of blocks in a page //! \tparam Pages_ number of pages //! \tparam BlkSize_ external block size in bytes, default is 2 MiB //! \tparam AllocStr_ one of allocation strategies: \c striping , \c RC , \c SR , or \c FR //! default is RC //! \tparam Pager_ pager type: //! - \c random , //! - \c lru , is default //! //! Memory consumption of constructed vector is BlkSize_*Pages_*PgSz_ bytes //! Configured vector type is available as \c STACK_GENERATOR<>::result.

//! Examples: //! - \c VECTOR_GENERATOR::result external vector of \c double's , //! - \c VECTOR_GENERATOR::result external vector of \c double's , //! with 8 blocks per page, //! - \c VECTOR_GENERATOR::result external vector of \c double's , //! with 8 blocks per page, 2 pages, 512 KiB blocks, Random Cyclic allocation //! and lru cache replacement strategy //! \warning Do not store references to the elements of an external vector. Such references //! might be invalidated during any following access to elements of the vector template < typename Tp_, unsigned PgSz_ = 4, unsigned Pages_ = 8, unsigned BlkSize_ = STXXL_DEFAULT_BLOCK_SIZE(Tp_), typename AllocStr_ = STXXL_DEFAULT_ALLOC_STRATEGY, pager_type Pager_ = lru > struct VECTOR_GENERATOR { typedef typename IF, random_pager >::result PagerType; typedef vector result; }; //! \} __STXXL_END_NAMESPACE namespace std { template < typename Tp_, unsigned PgSz_, typename PgTp_, unsigned BlkSize_, typename AllocStr_, typename SzTp_> void swap(stxxl::vector & a, stxxl::vector & b) { a.swap(b); } } #endif // !STXXL_VECTOR_HEADER // vim: et:ts=4:sw=4 stxxl-1.3.1/include/stxxl/bits/containers/deque.h0000644000175000017500000004154211535151017021706 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/containers/deque.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2006 Roman Dementiev * Copyright (C) 2008, 2009 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef _STXXL_DEQUE_H #define _STXXL_DEQUE_H #include #include __STXXL_BEGIN_NAMESPACE template class deque; template class const_deque_iterator; template class deque_iterator { typedef typename DequeType::size_type size_type; typedef typename DequeType::vector_type vector_type; typedef deque_iterator _Self; DequeType * Deque; size_type Offset; deque_iterator(DequeType * Deque_, size_type Offset_) : Deque(Deque_), Offset(Offset_) { } friend class const_deque_iterator; public: typedef typename DequeType::value_type value_type; typedef typename DequeType::pointer pointer; typedef typename DequeType::const_pointer const_pointer; typedef typename DequeType::reference reference; typedef typename DequeType::const_reference const_reference; typedef deque_iterator iterator; typedef const_deque_iterator const_iterator; friend class deque; typedef std::random_access_iterator_tag iterator_category; typedef typename DequeType::difference_type difference_type; deque_iterator() : Deque(NULL), Offset(0) { } difference_type operator - (const _Self & a) const { size_type SelfAbsOffset = (Offset >= Deque->begin_o) ? Offset : (Deque->Vector.size() + Offset); size_type aAbsOffset = (a.Offset >= Deque->begin_o) ? a.Offset : (Deque->Vector.size() + a.Offset); return SelfAbsOffset - aAbsOffset; } difference_type operator - (const const_iterator & a) const { size_type SelfAbsOffset = (Offset >= Deque->begin_o) ? Offset : (Deque->Vector.size() + Offset); size_type aAbsOffset = (a.Offset >= Deque->begin_o) ? a.Offset : (Deque->Vector.size() + a.Offset); return SelfAbsOffset - aAbsOffset; } _Self operator - (size_type op) const { return _Self(Deque, (Offset + Deque->Vector.size() - op) % Deque->Vector.size()); } _Self operator + (size_type op) const { return _Self(Deque, (Offset + op) % Deque->Vector.size()); } _Self & operator -= (size_type op) { Offset = (Offset + Deque->Vector.size() - op) % Deque->Vector.size(); return *this; } _Self & operator += (size_type op) { Offset = (Offset + op) % Deque->Vector.size(); return *this; } reference operator * () { return Deque->Vector[Offset]; } pointer operator -> () { return &(Deque->Vector[Offset]); } const_reference operator * () const { return Deque->Vector[Offset]; } const_pointer operator -> () const { return &(Deque->Vector[Offset]); } reference operator [] (size_type op) { return Deque->Vector[(Offset + op) % Deque->Vector.size()]; } const_reference operator [] (size_type op) const { return Deque->Vector[(Offset + op) % Deque->Vector.size()]; } _Self & operator ++ () { Offset = (Offset + 1) % Deque->Vector.size(); return *this; } _Self operator ++ (int) { _Self __tmp = *this; Offset = (Offset + 1) % Deque->Vector.size(); return __tmp; } _Self & operator -- () { Offset = (Offset + Deque->Vector.size() - 1) % Deque->Vector.size(); return *this; } _Self operator -- (int) { _Self __tmp = *this; Offset = (Offset + Deque->Vector.size() - 1) % Deque->Vector.size(); return __tmp; } bool operator == (const _Self & a) const { assert(Deque == a.Deque); return Offset == a.Offset; } bool operator != (const _Self & a) const { assert(Deque == a.Deque); return Offset != a.Offset; } bool operator < (const _Self & a) const { assert(Deque == a.Deque); return (a - (*this)) > 0; } bool operator > (const _Self & a) const { return a < (*this); } bool operator <= (const _Self & a) const { return !((*this) > a); } bool operator >= (const _Self & a) const { return !((*this) < a); } bool operator == (const const_iterator & a) const { assert(Deque == a.Deque); return Offset == a.Offset; } bool operator != (const const_iterator & a) const { assert(Deque == a.Deque); return Offset != a.Offset; } bool operator < (const const_iterator & a) const { assert(Deque == a.Deque); return (a - (*this)) > 0; } bool operator > (const const_iterator & a) const { return a < (*this); } bool operator <= (const const_iterator & a) const { return !((*this) > a); } bool operator >= (const const_iterator & a) const { return !((*this) < a); } }; template class const_deque_iterator { typedef const_deque_iterator _Self; typedef typename DequeType::size_type size_type; typedef typename DequeType::vector_type vector_type; const DequeType * Deque; size_type Offset; const_deque_iterator(const DequeType * Deque_, size_type Offset_) : Deque(Deque_), Offset(Offset_) { } public: typedef typename DequeType::value_type value_type; typedef typename DequeType::const_pointer pointer; typedef typename DequeType::const_pointer const_pointer; typedef typename DequeType::const_reference reference; typedef typename DequeType::const_reference const_reference; typedef deque_iterator iterator; typedef const_deque_iterator const_iterator; friend class deque; friend class deque_iterator; typedef std::random_access_iterator_tag iterator_category; typedef typename DequeType::difference_type difference_type; const_deque_iterator() : Deque(NULL), Offset(0) { } const_deque_iterator(const deque_iterator & it) : Deque(it.Deque), Offset(it.Offset) { } difference_type operator - (const _Self & a) const { size_type SelfAbsOffset = (Offset >= Deque->begin_o) ? Offset : (Deque->Vector.size() + Offset); size_type aAbsOffset = (a.Offset >= Deque->begin_o) ? a.Offset : (Deque->Vector.size() + a.Offset); return SelfAbsOffset - aAbsOffset; } difference_type operator - (const iterator & a) const { size_type SelfAbsOffset = (Offset >= Deque->begin_o) ? Offset : (Deque->Vector.size() + Offset); size_type aAbsOffset = (a.Offset >= Deque->begin_o) ? a.Offset : (Deque->Vector.size() + a.Offset); return SelfAbsOffset - aAbsOffset; } _Self operator - (size_type op) const { return _Self(Deque, (Offset + Deque->Vector.size() - op) % Deque->Vector.size()); } _Self operator + (size_type op) const { return _Self(Deque, (Offset + op) % Deque->Vector.size()); } _Self & operator -= (size_type op) { Offset = (Offset + Deque->Vector.size() - op) % Deque->Vector.size(); return *this; } _Self & operator += (size_type op) { Offset = (Offset + op) % Deque->Vector.size(); return *this; } const_reference operator * () const { return Deque->Vector[Offset]; } const_pointer operator -> () const { return &(Deque->Vector[Offset]); } const_reference operator [] (size_type op) const { return Deque->Vector[(Offset + op) % Deque->Vector.size()]; } _Self & operator ++ () { Offset = (Offset + 1) % Deque->Vector.size(); return *this; } _Self operator ++ (int) { _Self __tmp = *this; Offset = (Offset + 1) % Deque->Vector.size(); return __tmp; } _Self & operator -- () { Offset = (Offset + Deque->Vector.size() - 1) % Deque->Vector.size(); return *this; } _Self operator -- (int) { _Self __tmp = *this; Offset = (Offset + Deque->Vector.size() - 1) % Deque->Vector.size(); return __tmp; } bool operator == (const _Self & a) const { assert(Deque == a.Deque); return Offset == a.Offset; } bool operator != (const _Self & a) const { assert(Deque == a.Deque); return Offset != a.Offset; } bool operator < (const _Self & a) const { assert(Deque == a.Deque); return (a - (*this)) > 0; } bool operator > (const _Self & a) const { return a < (*this); } bool operator <= (const _Self & a) const { return !((*this) > a); } bool operator >= (const _Self & a) const { return !((*this) < a); } bool operator == (const iterator & a) const { assert(Deque == a.Deque); return Offset == a.Offset; } bool operator != (const iterator & a) const { assert(Deque == a.Deque); return Offset != a.Offset; } bool operator < (const iterator & a) const { assert(Deque == a.Deque); return (a - (*this)) > 0; } bool operator > (const iterator & a) const { return a < (*this); } bool operator <= (const iterator & a) const { return !((*this) > a); } bool operator >= (const iterator & a) const { return !((*this) < a); } }; //! \addtogroup stlcont //! \{ //! \brief A deque container //! //! It is an adaptor of the \c VectorType. //! The implementation wraps the elements around //! the end of the \c VectorType circularly. //! \tparam T type of the contained objects (POD with no references to internal memory) //! \tparam VectorType the type of the underlying vector container, //! the default is \c stxxl::vector template > class deque : private noncopyable { typedef deque Self_; public: typedef typename VectorType::size_type size_type; typedef typename VectorType::difference_type difference_type; typedef VectorType vector_type; typedef T value_type; typedef T * pointer; typedef const value_type * const_pointer; typedef T & reference; typedef const T & const_reference; typedef deque_iterator iterator; typedef const_deque_iterator const_iterator; typedef std::reverse_iterator reverse_iterator; typedef std::reverse_iterator const_reverse_iterator; friend class deque_iterator; friend class const_deque_iterator; private: VectorType Vector; size_type begin_o, end_o, size_; void double_array() { const size_type old_size = Vector.size(); Vector.resize(2 * old_size); if (begin_o > end_o) { // copy data to the new end of the vector const size_type new_begin_o = old_size + begin_o; std::copy(Vector.begin() + begin_o, Vector.begin() + old_size, Vector.begin() + new_begin_o); begin_o = new_begin_o; } } public: deque() : Vector((STXXL_DEFAULT_BLOCK_SIZE(T)) / sizeof(T)), begin_o(0), end_o(0), size_(0) { } deque(size_type n) : Vector(STXXL_MAX(STXXL_DEFAULT_BLOCK_SIZE(T) / sizeof(T), 2 * n)), begin_o(0), end_o(n), size_(n) { } ~deque() // empty so far { } iterator begin() { return iterator(this, begin_o); } iterator end() { return iterator(this, end_o); } const_iterator begin() const { return const_iterator(this, begin_o); } const_iterator cbegin() const { return begin(); } const_iterator end() const { return const_iterator(this, end_o); } const_iterator cend() const { return end(); } reverse_iterator rbegin() { return reverse_iterator(end()); } const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); } const_reverse_iterator crbegin() const { return const_reverse_iterator(end()); } reverse_iterator rend() { return reverse_iterator(begin()); } const_reverse_iterator rend() const { return const_reverse_iterator(begin()); } const_reverse_iterator crend() const { return const_reverse_iterator(begin()); } size_type size() const { return size_; } size_type max_size() const { return (std::numeric_limits::max)() / 2 - 1; } bool empty() const { return size_ == 0; } reference operator [] (size_type n) { assert(n < size()); return Vector[(begin_o + n) % Vector.size()]; } const_reference operator [] (size_type n) const { assert(n < size()); return Vector[(begin_o + n) % Vector.size()]; } reference front() { assert(!empty()); return Vector[begin_o]; } const_reference front() const { assert(!empty()); return Vector[begin_o]; } reference back() { assert(!empty()); return Vector[(end_o + Vector.size() - 1) % Vector.size()]; } const_reference back() const { assert(!empty()); return Vector[(end_o + Vector.size() - 1) % Vector.size()]; } void push_front(const T & el) { if ((begin_o + Vector.size() - 1) % Vector.size() == end_o) { // an overflow will occur: resize the array double_array(); } begin_o = (begin_o + Vector.size() - 1) % Vector.size(); Vector[begin_o] = el; ++size_; } void push_back(const T & el) { if ((end_o + 1) % Vector.size() == begin_o) { // an overflow will occur: resize the array double_array(); } Vector[end_o] = el; end_o = (end_o + 1) % Vector.size(); ++size_; } void pop_front() { assert(!empty()); begin_o = (begin_o + 1) % Vector.size(); --size_; } void pop_back() { assert(!empty()); end_o = (end_o + Vector.size() - 1) % Vector.size(); --size_; } void swap(deque & obj) { std::swap(Vector, obj.Vector); std::swap(begin_o, obj.begin_o); std::swap(end_o, obj.end_o); std::swap(size_, obj.size_); } void clear() { Vector.clear(); Vector.resize((STXXL_DEFAULT_BLOCK_SIZE(T)) / sizeof(T)); begin_o = 0; end_o = 0; size_ = 0; } void resize(size_type n) { if (n < size()) { do { pop_back(); } while (n < size()); } else { if (n + 1 > Vector.size()) { // need to resize const size_type old_size = Vector.size(); Vector.resize(2 * n); if (begin_o > end_o) { // copy data to the new end of the vector const size_type new_begin_o = Vector.size() - old_size + begin_o; std::copy(Vector.begin() + begin_o, Vector.begin() + old_size, Vector.begin() + new_begin_o); begin_o = new_begin_o; } } end_o = (end_o + n - size()) % Vector.size(); size_ = n; } } }; template bool operator == (const deque & a, const deque & b) { return std::equal(a.begin(), a.end(), b.begin()); } template bool operator < (const deque & a, const deque & b) { return std::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end()); } //! \} __STXXL_END_NAMESPACE namespace std { template void swap(stxxl::deque & a, stxxl::deque & b) { a.swap(b); } } #endif /* _STXXL_DEQUE_H */ stxxl-1.3.1/include/stxxl/bits/containers/pq_losertree.h0000644000175000017500000006456211531237734023325 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/containers/pq_losertree.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 1999 Peter Sanders * Copyright (C) 2003, 2004, 2007 Roman Dementiev * Copyright (C) 2007-2009 Johannes Singler * Copyright (C) 2007, 2008 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_PQ_LOSERTREE_HEADER #define STXXL_PQ_LOSERTREE_HEADER __STXXL_BEGIN_NAMESPACE //! \addtogroup stlcontinternals //! //! \{ /*! \internal */ namespace priority_queue_local { ////////////////////////////////////////////////////////////////////// // The data structure from Knuth, "Sorting and Searching", Section 5.4.1 /** *! \brief Loser tree from Knuth, "Sorting and Searching", Section 5.4.1 *! \param KNKMAX maximum arity of loser tree, has to be a power of two */ template class loser_tree : private noncopyable { public: typedef ValTp_ value_type; typedef Cmp_ comparator_type; typedef value_type Element; private: #if STXXL_PQ_INTERNAL_LOSER_TREE struct Entry { value_type key; // Key of Loser element (winner for 0) unsigned_type index; // number of losing segment }; #endif //STXXL_PQ_INTERNAL_LOSER_TREE comparator_type cmp; // stack of free segment indices internal_bounded_stack free_slots; unsigned_type size_; // total number of elements stored unsigned_type logK; // log of current tree size unsigned_type k; // invariant (k == 1 << logK), always a power of two Element sentinel; // target of free segment pointers #if STXXL_PQ_INTERNAL_LOSER_TREE // upper levels of loser trees // entry[0] contains the winner info Entry entry[KNKMAX]; #endif //STXXL_PQ_INTERNAL_LOSER_TREE // leaf information // note that Knuth uses indices k..k-1 // while we use 0..k-1 Element * current[KNKMAX]; // pointer to current element Element * current_end[KNKMAX]; // pointer to end of block for current element Element * segment[KNKMAX]; // start of Segments unsigned_type segment_size[KNKMAX]; // just to count the internal memory consumption, in bytes unsigned_type mem_cons_; // private member functions unsigned_type initWinner(unsigned_type root); void update_on_insert(unsigned_type node, const Element & newKey, unsigned_type newIndex, Element * winnerKey, unsigned_type * winnerIndex, unsigned_type * mask); void deallocate_segment(unsigned_type slot); void doubleK(); void compactTree(); void rebuildLoserTree(); bool is_segment_empty(unsigned_type slot); void multi_merge_k(Element * target, unsigned_type length); #if STXXL_PQ_INTERNAL_LOSER_TREE template void multi_merge_f(Element * target, unsigned_type length) { //Entry *currentPos; //Element currentKey; //int currentIndex; // leaf pointed to by current entry Element * done = target + length; Entry * regEntry = entry; Element ** regStates = current; unsigned_type winnerIndex = regEntry[0].index; Element winnerKey = regEntry[0].key; Element * winnerPos; //Element sup = sentinel; // supremum assert(logK >= LogK); while (target != done) { winnerPos = regStates[winnerIndex]; // write result *target = winnerKey; // advance winner segment ++winnerPos; regStates[winnerIndex] = winnerPos; winnerKey = *winnerPos; // remove winner segment if empty now if (is_sentinel(winnerKey)) { deallocate_segment(winnerIndex); } ++target; // update loser tree #define TreeStep(L) \ if (1 << LogK >= 1 << L) { \ Entry * pos ## L = regEntry + ((winnerIndex + (1 << LogK)) >> (((int(LogK - L) + 1) >= 0) ? ((LogK - L) + 1) : 0)); \ Element key ## L = pos ## L->key; \ if (cmp(winnerKey, key ## L)) { \ unsigned_type index ## L = pos ## L->index; \ pos ## L->key = winnerKey; \ pos ## L->index = winnerIndex; \ winnerKey = key ## L; \ winnerIndex = index ## L; \ } \ } TreeStep(10); TreeStep(9); TreeStep(8); TreeStep(7); TreeStep(6); TreeStep(5); TreeStep(4); TreeStep(3); TreeStep(2); TreeStep(1); #undef TreeStep } regEntry[0].index = winnerIndex; regEntry[0].key = winnerKey; } #endif //STXXL_PQ_INTERNAL_LOSER_TREE public: bool is_sentinel(const Element & a) { return !(cmp(cmp.min_value(), a)); } bool not_sentinel(const Element & a) { return cmp(cmp.min_value(), a); } public: loser_tree(); ~loser_tree(); void init(); void swap(loser_tree & obj) { std::swap(cmp, obj.cmp); std::swap(free_slots, obj.free_slots); std::swap(size_, obj.size_); std::swap(logK, obj.logK); std::swap(k, obj.k); std::swap(sentinel, obj.sentinel); #if STXXL_PQ_INTERNAL_LOSER_TREE swap_1D_arrays(entry, obj.entry, KNKMAX); #endif //STXXL_PQ_INTERNAL_LOSER_TREE swap_1D_arrays(current, obj.current, KNKMAX); swap_1D_arrays(current_end, obj.current_end, KNKMAX); swap_1D_arrays(segment, obj.segment, KNKMAX); swap_1D_arrays(segment_size, obj.segment_size, KNKMAX); std::swap(mem_cons_, obj.mem_cons_); } void multi_merge(Element * begin, Element * end) { multi_merge(begin, end - begin); } void multi_merge(Element *, unsigned_type length); unsigned_type mem_cons() const { return mem_cons_; } bool is_space_available() const // for new segment { return (k < KNKMAX) || !free_slots.empty(); } void insert_segment(Element * target, unsigned_type length); // insert segment beginning at target unsigned_type size() { return size_; } }; ///////////////////////// LoserTree /////////////////////////////////// template loser_tree::loser_tree() : size_(0), logK(0), k(1), mem_cons_(0) { free_slots.push(0); segment[0] = NULL; current[0] = &sentinel; current_end[0] = &sentinel; // entry and sentinel are initialized by init // since they need the value of supremum init(); } template void loser_tree::init() { assert(!cmp(cmp.min_value(), cmp.min_value())); // verify strict weak ordering sentinel = cmp.min_value(); rebuildLoserTree(); #if STXXL_PQ_INTERNAL_LOSER_TREE assert(current[entry[0].index] == &sentinel); #endif //STXXL_PQ_INTERNAL_LOSER_TREE } // rebuild loser tree information from the values in current template void loser_tree::rebuildLoserTree() { #if STXXL_PQ_INTERNAL_LOSER_TREE assert(LOG2::floor == LOG2::ceil); // KNKMAX needs to be a power of two unsigned_type winner = initWinner(1); entry[0].index = winner; entry[0].key = *(current[winner]); #endif //STXXL_PQ_INTERNAL_LOSER_TREE } #if STXXL_PQ_INTERNAL_LOSER_TREE // given any values in the leaves this // routing recomputes upper levels of the tree // from scratch in linear time // initialize entry[root].index and the subtree rooted there // return winner index template unsigned_type loser_tree::initWinner(unsigned_type root) { if (root >= k) { // leaf reached return root - k; } else { unsigned_type left = initWinner(2 * root); unsigned_type right = initWinner(2 * root + 1); Element lk = *(current[left]); Element rk = *(current[right]); if (!(cmp(lk, rk))) { // right subtree loses entry[root].index = right; entry[root].key = rk; return left; } else { entry[root].index = left; entry[root].key = lk; return right; } } } // first go up the tree all the way to the root // hand down old winner for the respective subtree // based on new value, and old winner and loser // update each node on the path to the root top down. // This is implemented recursively template void loser_tree::update_on_insert( unsigned_type node, const Element & newKey, unsigned_type newIndex, Element * winnerKey, unsigned_type * winnerIndex, // old winner unsigned_type * mask) // 1 << (ceil(log KNK) - dist-from-root) { if (node == 0) { // winner part of root *mask = 1 << (logK - 1); *winnerKey = entry[0].key; *winnerIndex = entry[0].index; if (cmp(entry[node].key, newKey)) { entry[node].key = newKey; entry[node].index = newIndex; } } else { update_on_insert(node >> 1, newKey, newIndex, winnerKey, winnerIndex, mask); Element loserKey = entry[node].key; unsigned_type loserIndex = entry[node].index; if ((*winnerIndex & *mask) != (newIndex & *mask)) { // different subtrees if (cmp(loserKey, newKey)) { // newKey will have influence here if (cmp(*winnerKey, newKey)) { // old winner loses here entry[node].key = *winnerKey; entry[node].index = *winnerIndex; } else { // new entry loses here entry[node].key = newKey; entry[node].index = newIndex; } } *winnerKey = loserKey; *winnerIndex = loserIndex; } // note that nothing needs to be done if // the winner came from the same subtree // a) newKey <= winnerKey => even more reason for the other tree to lose // b) newKey > winnerKey => the old winner will beat the new // entry further down the tree // also the same old winner is handed down the tree *mask >>= 1; // next level } } #endif //STXXL_PQ_INTERNAL_LOSER_TREE // make the tree two times as wide template void loser_tree::doubleK() { STXXL_VERBOSE3("loser_tree::doubleK (before) k=" << k << " logK=" << logK << " KNKMAX=" << KNKMAX << " #free=" << free_slots.size()); assert(k > 0); assert(k < KNKMAX); assert(free_slots.empty()); // stack was free (probably not needed) // make all new entries free // and push them on the free stack for (unsigned_type i = 2 * k - 1; i >= k; i--) // backwards { current[i] = &sentinel; current_end[i] = &sentinel; segment[i] = NULL; free_slots.push(i); } // double the size k *= 2; logK++; STXXL_VERBOSE3("loser_tree::doubleK (after) k=" << k << " logK=" << logK << " KNKMAX=" << KNKMAX << " #free=" << free_slots.size()); assert(!free_slots.empty()); // recompute loser tree information rebuildLoserTree(); } // compact nonempty segments in the left half of the tree template void loser_tree::compactTree() { STXXL_VERBOSE3("loser_tree::compactTree (before) k=" << k << " logK=" << logK << " #free=" << free_slots.size()); assert(logK > 0); // compact all nonempty segments to the left unsigned_type pos = 0; unsigned_type last_empty = 0; for ( ; pos < k; pos++) { if (not_sentinel(*(current[pos]))) { segment_size[last_empty] = segment_size[pos]; current[last_empty] = current[pos]; current_end[last_empty] = current_end[pos]; segment[last_empty] = segment[pos]; last_empty++; } /* else { if(segment[pos]) { STXXL_VERBOSE2("loser_tree::compactTree() deleting segment "< 1) && ((k / 2) >= last_empty)) { k /= 2; logK--; } // overwrite garbage and compact the stack of free segment indices free_slots.clear(); // none free for ( ; last_empty < k; last_empty++) { current[last_empty] = &sentinel; current_end[last_empty] = &sentinel; free_slots.push(last_empty); } STXXL_VERBOSE3("loser_tree::compactTree (after) k=" << k << " logK=" << logK << " #free=" << free_slots.size()); // recompute loser tree information rebuildLoserTree(); } // insert segment beginning at target // require: is_space_available() == 1 template void loser_tree::insert_segment(Element * target, unsigned_type length) { STXXL_VERBOSE2("loser_tree::insert_segment(" << target << "," << length << ")"); //std::copy(target,target + length,std::ostream_iterator(std::cout, "\n")); if (length > 0) { assert(not_sentinel(target[0])); assert(not_sentinel(target[length - 1])); assert(is_sentinel(target[length])); // get a free slot if (free_slots.empty()) { // tree is too small doubleK(); } assert(!free_slots.empty()); unsigned_type index = free_slots.top(); free_slots.pop(); // link new segment current[index] = segment[index] = target; current_end[index] = target + length; segment_size[index] = (length + 1) * sizeof(value_type); mem_cons_ += (length + 1) * sizeof(value_type); size_ += length; #if STXXL_PQ_INTERNAL_LOSER_TREE // propagate new information up the tree Element dummyKey; unsigned_type dummyIndex; unsigned_type dummyMask; update_on_insert((index + k) >> 1, *target, index, &dummyKey, &dummyIndex, &dummyMask); #endif //STXXL_PQ_INTERNAL_LOSER_TREE } else { // immediately deallocate // this is not only an optimization // but also needed to keep free segments from // clogging up the tree delete[] target; } } template loser_tree::~loser_tree() { STXXL_VERBOSE1("loser_tree::~loser_tree()"); for (unsigned_type i = 0; i < k; ++i) { if (segment[i]) { STXXL_VERBOSE2("loser_tree::~loser_tree() deleting segment " << i); delete[] segment[i]; mem_cons_ -= segment_size[i]; } } // check whether we have not lost any memory assert(mem_cons_ == 0); } // free an empty segment . template void loser_tree::deallocate_segment(unsigned_type slot) { // reroute current pointer to some empty sentinel segment // with a sentinel key STXXL_VERBOSE2("loser_tree::deallocate_segment() deleting segment " << slot << " address: " << segment[slot] << " size: " << (segment_size[slot] / sizeof(value_type)) - 1); current[slot] = &sentinel; current_end[slot] = &sentinel; // free memory delete[] segment[slot]; segment[slot] = NULL; mem_cons_ -= segment_size[slot]; // push on the stack of free segment indices free_slots.push(slot); } // delete the length smallest elements and write them to target // empty segments are deallocated // require: // - there are at least length elements // - segments are ended by sentinels template void loser_tree::multi_merge(Element * target, unsigned_type length) { STXXL_VERBOSE3("loser_tree::multi_merge(target=" << target << ", len=" << length << ") k=" << k); if (length == 0) return; assert(k > 0); assert(length <= size_); //This is the place to make statistics about internal multi_merge calls. #if STXXL_PARALLEL && STXXL_PARALLEL_PQ_MULTIWAY_MERGE_INTERNAL priority_queue_local::invert_order inv_cmp(cmp); #endif switch (logK) { case 0: assert(k == 1); #if STXXL_PQ_INTERNAL_LOSER_TREE assert(entry[0].index == 0); #endif //STXXL_PQ_INTERNAL_LOSER_TREE assert(free_slots.empty()); memcpy(target, current[0], length * sizeof(Element)); //std::copy(current[0], current[0] + length, target); current[0] += length; #if STXXL_PQ_INTERNAL_LOSER_TREE entry[0].key = **current; #endif //STXXL_PQ_INTERNAL_LOSER_TREE if (is_segment_empty(0)) deallocate_segment(0); break; case 1: assert(k == 2); #if STXXL_PARALLEL && STXXL_PARALLEL_PQ_MULTIWAY_MERGE_INTERNAL { std::pair seqs[2] = { std::make_pair(current[0], current_end[0]), std::make_pair(current[1], current_end[1]) }; parallel::multiway_merge_sentinel(seqs, seqs + 2, target, inv_cmp, length); current[0] = seqs[0].first; current[1] = seqs[1].first; } #else merge_iterator(current[0], current[1], target, length, cmp); rebuildLoserTree(); #endif if (is_segment_empty(0)) deallocate_segment(0); if (is_segment_empty(1)) deallocate_segment(1); break; case 2: assert(k == 4); #if STXXL_PARALLEL && STXXL_PARALLEL_PQ_MULTIWAY_MERGE_INTERNAL { std::pair seqs[4] = { std::make_pair(current[0], current_end[0]), std::make_pair(current[1], current_end[1]), std::make_pair(current[2], current_end[2]), std::make_pair(current[3], current_end[3]) }; parallel::multiway_merge_sentinel(seqs, seqs + 4, target, inv_cmp, length); current[0] = seqs[0].first; current[1] = seqs[1].first; current[2] = seqs[2].first; current[3] = seqs[3].first; } #else if (is_segment_empty(3)) merge3_iterator(current[0], current[1], current[2], target, length, cmp); else merge4_iterator(current[0], current[1], current[2], current[3], target, length, cmp); rebuildLoserTree(); #endif if (is_segment_empty(0)) deallocate_segment(0); if (is_segment_empty(1)) deallocate_segment(1); if (is_segment_empty(2)) deallocate_segment(2); if (is_segment_empty(3)) deallocate_segment(3); break; #if !(STXXL_PARALLEL && STXXL_PARALLEL_PQ_MULTIWAY_MERGE_INTERNAL) case 3: multi_merge_f<3>(target, length); break; case 4: multi_merge_f<4>(target, length); break; case 5: multi_merge_f<5>(target, length); break; case 6: multi_merge_f<6>(target, length); break; case 7: multi_merge_f<7>(target, length); break; case 8: multi_merge_f<8>(target, length); break; case 9: multi_merge_f<9>(target, length); break; case 10: multi_merge_f<10>(target, length); break; #endif default: #if STXXL_PARALLEL && STXXL_PARALLEL_PQ_MULTIWAY_MERGE_INTERNAL { std::vector > seqs; std::vector orig_seq_index; for (unsigned int i = 0; i < k; ++i) { if (current[i] != current_end[i] && !is_sentinel(*current[i])) { seqs.push_back(std::make_pair(current[i], current_end[i])); orig_seq_index.push_back(i); } } parallel::multiway_merge_sentinel(seqs.begin(), seqs.end(), target, inv_cmp, length); for (unsigned int i = 0; i < seqs.size(); ++i) { int_type seg = orig_seq_index[i]; current[seg] = seqs[i].first; } for (unsigned int i = 0; i < k; ++i) if (is_segment_empty(i)) { STXXL_VERBOSE3("deallocated " << i); deallocate_segment(i); } } #else multi_merge_k(target, length); #endif break; } size_ -= length; // compact tree if it got considerably smaller { const unsigned_type num_segments_used = k - free_slots.size(); const unsigned_type num_segments_trigger = k - (3 * k / 5); // using k/2 would be worst case inefficient (for large k) // for k \in {2, 4, 8} the trigger is k/2 which is good // because we have special mergers for k \in {1, 2, 4} // there is also a special 3-way-merger, that will be // triggered if k == 4 && is_segment_empty(3) STXXL_VERBOSE3("loser_tree compact? k=" << k << " #used=" << num_segments_used << " <= #trigger=" << num_segments_trigger << " ==> " << ((k > 1 && num_segments_used <= num_segments_trigger) ? "yes" : "no ") << " || " << ((k == 4 && !free_slots.empty() && !is_segment_empty(3)) ? "yes" : "no ") << " #free=" << free_slots.size()); if (k > 1 && ((num_segments_used <= num_segments_trigger) || (k == 4 && !free_slots.empty() && !is_segment_empty(3)))) { compactTree(); } } //std::copy(target,target + length,std::ostream_iterator(std::cout, "\n")); } // is this segment empty and does not point to sentinel yet? template inline bool loser_tree::is_segment_empty(unsigned_type slot) { return (is_sentinel(*(current[slot])) && (current[slot] != &sentinel)); } #if STXXL_PQ_INTERNAL_LOSER_TREE // multi-merge for arbitrary K template void loser_tree:: multi_merge_k(Element * target, unsigned_type length) { Entry * currentPos; Element currentKey; unsigned_type currentIndex; // leaf pointed to by current entry unsigned_type kReg = k; Element * done = target + length; unsigned_type winnerIndex = entry[0].index; Element winnerKey = entry[0].key; Element * winnerPos; while (target != done) { winnerPos = current[winnerIndex]; // write result *target = winnerKey; // advance winner segment ++winnerPos; current[winnerIndex] = winnerPos; winnerKey = *winnerPos; // remove winner segment if empty now if (is_sentinel(winnerKey)) // deallocate_segment(winnerIndex); // go up the entry-tree for (unsigned_type i = (winnerIndex + kReg) >> 1; i > 0; i >>= 1) { currentPos = entry + i; currentKey = currentPos->key; if (cmp(winnerKey, currentKey)) { currentIndex = currentPos->index; currentPos->key = winnerKey; currentPos->index = winnerIndex; winnerKey = currentKey; winnerIndex = currentIndex; } } ++target; } entry[0].index = winnerIndex; entry[0].key = winnerKey; } #endif //STXXL_PQ_INTERNAL_LOSER_TREE } //priority_queue_local //! \} __STXXL_END_NAMESPACE #endif // !STXXL_PQ_LOSERTREE_HEADER // vim: et:ts=4:sw=4 stxxl-1.3.1/include/stxxl/bits/containers/pq_mergers.h0000644000175000017500000001614711531237734022761 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/containers/pq_mergers.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 1999 Peter Sanders * Copyright (C) 2003, 2004, 2007 Roman Dementiev * Copyright (C) 2007-2009 Johannes Singler * Copyright (C) 2007, 2008 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_PQ_MERGERS_HEADER #define STXXL_PQ_MERGERS_HEADER __STXXL_BEGIN_NAMESPACE //! \addtogroup stlcontinternals //! //! \{ /*! \internal */ namespace priority_queue_local { ///////////////////////////////////////////////////////////////////// // auxiliary functions // merge length elements from the two sentinel terminated input // sequences source0 and source1 to target // advance source0 and source1 accordingly // require: at least length nonsentinel elements available in source0, source1 // require: target may overwrite one of the sources as long as // *(sourcex + length) is before the end of sourcex template void merge_iterator( InputIterator & source0, InputIterator & source1, OutputIterator target, unsigned_type length, Cmp_ cmp) { OutputIterator done = target + length; while (target != done) { if (cmp(*source0, *source1)) { *target = *source1; ++source1; } else { *target = *source0; ++source0; } ++target; } } // merge length elements from the three sentinel terminated input // sequences source0, source1 and source2 to target // advance source0, source1 and source2 accordingly // require: at least length nonsentinel elements available in source0, source1 and source2 // require: target may overwrite one of the sources as long as // *(sourcex + length) is before the end of sourcex template void merge3_iterator( InputIterator & source0, InputIterator & source1, InputIterator & source2, OutputIterator target, unsigned_type length, Cmp_ cmp) { OutputIterator done = target + length; if (cmp(*source1, *source0)) { if (cmp(*source2, *source1)) { goto s012; } else { if (cmp(*source0, *source2)) { goto s201; } else { goto s021; } } } else { if (cmp(*source2, *source1)) { if (cmp(*source2, *source0)) { goto s102; } else { goto s120; } } else { goto s210; } } #define Merge3Case(a, b, c) \ s ## a ## b ## c : \ if (target == done) \ return; \ *target = *source ## a; \ ++target; \ ++source ## a; \ if (cmp(*source ## b, *source ## a)) \ goto s ## a ## b ## c; \ if (cmp(*source ## c, *source ## a)) \ goto s ## b ## a ## c; \ goto s ## b ## c ## a; // the order is chosen in such a way that // four of the trailing gotos can be eliminated by the optimizer Merge3Case(0, 1, 2); Merge3Case(1, 2, 0); Merge3Case(2, 0, 1); Merge3Case(1, 0, 2); Merge3Case(0, 2, 1); Merge3Case(2, 1, 0); #undef Merge3Case } // merge length elements from the four sentinel terminated input // sequences source0, source1, source2 and source3 to target // advance source0, source1, source2 and source3 accordingly // require: at least length nonsentinel elements available in source0, source1, source2 and source3 // require: target may overwrite one of the sources as long as // *(sourcex + length) is before the end of sourcex template void merge4_iterator( InputIterator & source0, InputIterator & source1, InputIterator & source2, InputIterator & source3, OutputIterator target, unsigned_type length, Cmp_ cmp) { OutputIterator done = target + length; #define StartMerge4(a, b, c, d) \ if ((!cmp(*source ## a, *source ## b)) && (!cmp(*source ## b, *source ## c)) && (!cmp(*source ## c, *source ## d))) \ goto s ## a ## b ## c ## d; // b>a c>b d>c // ab) !(b>c) !(c>d) StartMerge4(0, 1, 2, 3); StartMerge4(1, 2, 3, 0); StartMerge4(2, 3, 0, 1); StartMerge4(3, 0, 1, 2); StartMerge4(0, 3, 1, 2); StartMerge4(3, 1, 2, 0); StartMerge4(1, 2, 0, 3); StartMerge4(2, 0, 3, 1); StartMerge4(0, 2, 3, 1); StartMerge4(2, 3, 1, 0); StartMerge4(3, 1, 0, 2); StartMerge4(1, 0, 2, 3); StartMerge4(2, 0, 1, 3); StartMerge4(0, 1, 3, 2); StartMerge4(1, 3, 2, 0); StartMerge4(3, 2, 0, 1); StartMerge4(3, 0, 2, 1); StartMerge4(0, 2, 1, 3); StartMerge4(2, 1, 3, 0); StartMerge4(1, 3, 0, 2); StartMerge4(1, 0, 3, 2); StartMerge4(0, 3, 2, 1); StartMerge4(3, 2, 1, 0); StartMerge4(2, 1, 0, 3); #define Merge4Case(a, b, c, d) \ s ## a ## b ## c ## d : \ if (target == done) \ return; \ *target = *source ## a; \ ++target; \ ++source ## a; \ if (cmp(*source ## c, *source ## a)) \ { \ if (cmp(*source ## b, *source ## a)) \ goto s ## a ## b ## c ## d; \ else \ goto s ## b ## a ## c ## d; \ } \ else \ { \ if (cmp(*source ## d, *source ## a)) \ goto s ## b ## c ## a ## d; \ else \ goto s ## b ## c ## d ## a; \ } Merge4Case(0, 1, 2, 3); Merge4Case(1, 2, 3, 0); Merge4Case(2, 3, 0, 1); Merge4Case(3, 0, 1, 2); Merge4Case(0, 3, 1, 2); Merge4Case(3, 1, 2, 0); Merge4Case(1, 2, 0, 3); Merge4Case(2, 0, 3, 1); Merge4Case(0, 2, 3, 1); Merge4Case(2, 3, 1, 0); Merge4Case(3, 1, 0, 2); Merge4Case(1, 0, 2, 3); Merge4Case(2, 0, 1, 3); Merge4Case(0, 1, 3, 2); Merge4Case(1, 3, 2, 0); Merge4Case(3, 2, 0, 1); Merge4Case(3, 0, 2, 1); Merge4Case(0, 2, 1, 3); Merge4Case(2, 1, 3, 0); Merge4Case(1, 3, 0, 2); Merge4Case(1, 0, 3, 2); Merge4Case(0, 3, 2, 1); Merge4Case(3, 2, 1, 0); Merge4Case(2, 1, 0, 3); #undef StartMerge4 #undef Merge4Case } } //priority_queue_local //! \} __STXXL_END_NAMESPACE #endif // !STXXL_PQ_MERGERS_HEADER // vim: et:ts=4:sw=4 stxxl-1.3.1/include/stxxl/bits/containers/queue.h0000644000175000017500000002517611535151017021734 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/containers/queue.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2005 Roman Dementiev * Copyright (C) 2009, 2010 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_QUEUE_HEADER #define STXXL_QUEUE_HEADER #include #include #include #include #include #include #include #include #include #include #include __STXXL_BEGIN_NAMESPACE #ifndef STXXL_VERBOSE_QUEUE #define STXXL_VERBOSE_QUEUE STXXL_VERBOSE2 #endif //! \addtogroup stlcont //! \{ //! \brief External FIFO queue container //! \tparam ValTp type of the contained objects (POD with no references to internal memory) //! \tparam BlkSz size of the external memory block in bytes, default is \c STXXL_DEFAULT_BLOCK_SIZE(ValTp) //! \tparam AllocStr parallel disk allocation strategy, default is \c STXXL_DEFAULT_ALLOC_STRATEGY //! \tparam SzTp size data type, default is \c stxxl::uint64 template class queue : private noncopyable { public: typedef ValTp value_type; typedef AllocStr alloc_strategy_type; typedef SzTp size_type; enum { block_size = BlkSz }; typedef typed_block block_type; typedef BID bid_type; private: typedef read_write_pool pool_type; size_type size_; bool delete_pool; pool_type * pool; block_type * front_block; block_type * back_block; value_type * front_element; value_type * back_element; alloc_strategy_type alloc_strategy; unsigned_type alloc_count; std::deque bids; block_manager * bm; unsigned_type blocks2prefetch; public: //! \brief Constructs empty queue with own write and prefetch block pool //! \param w_pool_size number of blocks in the write pool, must be at least 2, recommended at least 3 //! \param p_pool_size number of blocks in the prefetch pool, recommended at least 1 //! \param blocks2prefetch_ defines the number of blocks to prefetch (\c front side), //! default is number of block in the prefetch pool explicit queue(unsigned_type w_pool_size = 3, unsigned_type p_pool_size = 1, int blocks2prefetch_ = -1) : size_(0), delete_pool(true), alloc_count(0), bm(block_manager::get_instance()) { STXXL_VERBOSE_QUEUE("queue[" << this << "]::queue(sizes)"); pool = new pool_type(p_pool_size, w_pool_size); init(blocks2prefetch_); } //! \brief Constructs empty queue //! \param w_pool write pool //! \param p_pool prefetch pool //! \param blocks2prefetch_ defines the number of blocks to prefetch (\c front side), //! default is number of blocks in the prefetch pool //! \warning Number of blocks in the write pool must be at least 2, recommended at least 3 //! \warning Number of blocks in the prefetch pool recommended at least 1 _STXXL_DEPRECATED( queue(write_pool & w_pool, prefetch_pool & p_pool, int blocks2prefetch_ = -1)) : size_(0), delete_pool(true), alloc_count(0), bm(block_manager::get_instance()) { STXXL_VERBOSE_QUEUE("queue[" << this << "]::queue(pools)"); pool = new pool_type(w_pool, p_pool); init(blocks2prefetch_); } //! \brief Constructs empty queue //! \param pool_ block write/prefetch pool //! \param blocks2prefetch_ defines the number of blocks to prefetch (\c front side), //! default is number of blocks in the prefetch pool //! \warning Number of blocks in the write pool must be at least 2, recommended at least 3 //! \warning Number of blocks in the prefetch pool recommended at least 1 queue(pool_type & pool_, int blocks2prefetch_ = -1) : size_(0), delete_pool(false), pool(&pool_), alloc_count(0), bm(block_manager::get_instance()) { STXXL_VERBOSE_QUEUE("queue[" << this << "]::queue(pool)"); init(blocks2prefetch_); } private: void init(int blocks2prefetch_) { if (pool->size_write() < 2) { STXXL_ERRMSG("queue: invalid configuration, not enough blocks (" << pool->size_write() << ") in write pool, at least 2 are needed, resizing to 3"); pool->resize_write(3); } if (pool->size_write() < 3) { STXXL_MSG("queue: inefficient configuration, no blocks for buffered writing available"); } if (pool->size_prefetch() < 1) { STXXL_MSG("queue: inefficient configuration, no blocks for prefetching available"); } front_block = back_block = pool->steal(); back_element = back_block->begin() - 1; front_element = back_block->begin(); set_prefetch_aggr(blocks2prefetch_); } public: //! \brief Defines the number of blocks to prefetch (\c front side) //! This method should be called whenever the prefetch pool is resized //! \param blocks2prefetch_ defines the number of blocks to prefetch (\c front side), //! a negative value means to use the number of blocks in the prefetch pool void set_prefetch_aggr(int_type blocks2prefetch_) { if (blocks2prefetch_ < 0) blocks2prefetch = pool->size_prefetch(); else blocks2prefetch = blocks2prefetch_; } //! \brief Returns the number of blocks prefetched from the \c front side unsigned_type get_prefetch_aggr() const { return blocks2prefetch; } //! \brief Adds an element in the queue void push(const value_type & val) { if (back_element == back_block->begin() + (block_type::size - 1)) { // back block is filled if (front_block == back_block) { // can not write the back block because it // is the same as the front block, must keep it memory STXXL_VERBOSE1("queue::push Case 1"); } else { STXXL_VERBOSE1("queue::push Case 2"); // write the back block // need to allocate new block bid_type newbid; bm->new_block(alloc_strategy, newbid, alloc_count++); STXXL_VERBOSE_QUEUE("queue[" << this << "]: push block " << back_block << " @ " << FMT_BID(newbid)); bids.push_back(newbid); pool->write(back_block, newbid); if (bids.size() <= blocks2prefetch) { STXXL_VERBOSE1("queue::push Case Hints"); pool->hint(newbid); } } back_block = pool->steal(); back_element = back_block->begin(); *back_element = val; ++size_; return; } ++back_element; *back_element = val; ++size_; } //! \brief Removes element from the queue void pop() { assert(!empty()); if (front_element == front_block->begin() + (block_type::size - 1)) { // if there is only one block, it implies ... if (back_block == front_block) { STXXL_VERBOSE1("queue::pop Case 3"); assert(size() == 1); assert(back_element == front_element); assert(bids.empty()); // reset everything back_element = back_block->begin() - 1; front_element = back_block->begin(); size_ = 0; return; } --size_; if (size_ <= block_type::size) { STXXL_VERBOSE1("queue::pop Case 4"); assert(bids.empty()); // the back_block is the next block pool->add(front_block); front_block = back_block; front_element = back_block->begin(); return; } STXXL_VERBOSE1("queue::pop Case 5"); assert(!bids.empty()); request_ptr req = pool->read(front_block, bids.front()); STXXL_VERBOSE_QUEUE("queue[" << this << "]: pop block " << front_block << " @ " << FMT_BID(bids.front())); // give prefetching hints for (unsigned_type i = 0; i < blocks2prefetch && i < bids.size() - 1; ++i) { STXXL_VERBOSE1("queue::pop Case Hints"); pool->hint(bids[i + 1]); } front_element = front_block->begin(); req->wait(); bm->delete_block(bids.front()); bids.pop_front(); return; } ++front_element; --size_; } //! \brief Returns the size of the queue size_type size() const { return size_; } //! \brief Returns \c true if queue is empty bool empty() const { return (size_ == 0); } //! \brief Returns a mutable reference at the back of the queue value_type & back() { assert(!empty()); return *back_element; } //! \brief Returns a const reference at the back of the queue const value_type & back() const { assert(!empty()); return *back_element; } //! \brief Returns a mutable reference at the front of the queue value_type & front() { assert(!empty()); return *front_element; } //! \brief Returns a const reference at the front of the queue const value_type & front() const { assert(!empty()); return *front_element; } ~queue() { pool->add(front_block); if (front_block != back_block) pool->add(back_block); if (delete_pool) { delete pool; } if (!bids.empty()) bm->delete_blocks(bids.begin(), bids.end()); } }; //! \} __STXXL_END_NAMESPACE #endif // !STXXL_QUEUE_HEADER // vim: et:ts=4:sw=4 stxxl-1.3.1/include/stxxl/bits/containers/priority_queue.h0000644000175000017500000011377211535151017023675 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/containers/priority_queue.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 1999 Peter Sanders * Copyright (C) 2003, 2004, 2007 Roman Dementiev * Copyright (C) 2007-2009 Johannes Singler * Copyright (C) 2007-2010 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_PRIORITY_QUEUE_HEADER #define STXXL_PRIORITY_QUEUE_HEADER #include #include #include #include #include #include #include #include #include #include #include #if STXXL_PARALLEL #if defined(STXXL_PARALLEL_MODE) && ((__GNUC__ * 10000 + __GNUC_MINOR__ * 100) < 40400) #undef STXXL_PARALLEL_PQ_MULTIWAY_MERGE_INTERNAL #undef STXXL_PARALLEL_PQ_MULTIWAY_MERGE_EXTERNAL #undef STXXL_PARALLEL_PQ_MULTIWAY_MERGE_DELETE_BUFFER #define STXXL_PARALLEL_PQ_MULTIWAY_MERGE_INTERNAL 0 #define STXXL_PARALLEL_PQ_MULTIWAY_MERGE_EXTERNAL 0 #define STXXL_PARALLEL_PQ_MULTIWAY_MERGE_DELETE_BUFFER 0 #endif // enable/disable parallel merging for certain cases, for performance tuning #ifndef STXXL_PARALLEL_PQ_MULTIWAY_MERGE_INTERNAL #define STXXL_PARALLEL_PQ_MULTIWAY_MERGE_INTERNAL 1 #endif #ifndef STXXL_PARALLEL_PQ_MULTIWAY_MERGE_EXTERNAL #define STXXL_PARALLEL_PQ_MULTIWAY_MERGE_EXTERNAL 1 #endif #ifndef STXXL_PARALLEL_PQ_MULTIWAY_MERGE_DELETE_BUFFER #define STXXL_PARALLEL_PQ_MULTIWAY_MERGE_DELETE_BUFFER 1 #endif #endif //STXXL_PARALLEL #if STXXL_PARALLEL && STXXL_PARALLEL_PQ_MULTIWAY_MERGE_EXTERNAL #define STXXL_PQ_EXTERNAL_LOSER_TREE 0 // no loser tree for the external sequences #else #define STXXL_PQ_EXTERNAL_LOSER_TREE 1 #endif #if STXXL_PARALLEL && STXXL_PARALLEL_PQ_MULTIWAY_MERGE_INTERNAL #define STXXL_PQ_INTERNAL_LOSER_TREE 0 // no loser tree for the internal sequences #else #define STXXL_PQ_INTERNAL_LOSER_TREE 1 #endif #include #include #include #include __STXXL_BEGIN_NAMESPACE /* KNBufferSize1 = 32; KNN = 512; // length of group 1 sequences KNKMAX = 64; // maximal arity LogKNKMAX = 6; // ceil(log KNKMAX) KNLevels = 4; // overall capacity >= KNN*KNKMAX^KNLevels */ // internal memory consumption >= N_*(KMAX_^IntLevels_) + ext template < class Tp_, class Cmp_, unsigned BufferSize1_ = 32, // equalize procedure call overheads etc. unsigned N_ = 512, // length of group 1 sequences unsigned IntKMAX_ = 64, // maximal arity for internal mergers unsigned IntLevels_ = 4, // number of internal groups unsigned BlockSize_ = (2 * 1024 * 1024), // external block size unsigned ExtKMAX_ = 64, // maximal arity for external mergers unsigned ExtLevels_ = 2, // number of external groups class AllocStr_ = STXXL_DEFAULT_ALLOC_STRATEGY > struct priority_queue_config { typedef Tp_ value_type; typedef Cmp_ comparator_type; typedef AllocStr_ alloc_strategy_type; enum { delete_buffer_size = BufferSize1_, N = N_, IntKMAX = IntKMAX_, num_int_groups = IntLevels_, num_ext_groups = ExtLevels_, BlockSize = BlockSize_, ExtKMAX = ExtKMAX_, element_size = sizeof(Tp_) }; }; __STXXL_END_NAMESPACE namespace std { template void swap(stxxl::priority_queue_local::ext_merger & a, stxxl::priority_queue_local::ext_merger & b) { a.swap(b); } template void swap(stxxl::priority_queue_local::loser_tree & a, stxxl::priority_queue_local::loser_tree & b) { a.swap(b); } } __STXXL_BEGIN_NAMESPACE //! \brief External priority queue data structure template class priority_queue : private noncopyable { public: typedef Config_ Config; enum { delete_buffer_size = Config::delete_buffer_size, N = Config::N, IntKMAX = Config::IntKMAX, num_int_groups = Config::num_int_groups, num_ext_groups = Config::num_ext_groups, total_num_groups = Config::num_int_groups + Config::num_ext_groups, BlockSize = Config::BlockSize, ExtKMAX = Config::ExtKMAX }; //! \brief The type of object stored in the \b priority_queue typedef typename Config::value_type value_type; //! \brief Comparison object typedef typename Config::comparator_type comparator_type; typedef typename Config::alloc_strategy_type alloc_strategy_type; //! \brief An unsigned integral type (64 bit) typedef stxxl::uint64 size_type; typedef typed_block block_type; typedef read_write_pool pool_type; protected: typedef priority_queue_local::internal_priority_queue, comparator_type> insert_heap_type; typedef priority_queue_local::loser_tree< value_type, comparator_type, IntKMAX> int_merger_type; typedef priority_queue_local::ext_merger< block_type, comparator_type, ExtKMAX, alloc_strategy_type> ext_merger_type; int_merger_type int_mergers[num_int_groups]; pool_type * pool; bool pool_owned; ext_merger_type * ext_mergers; // one delete buffer for each tree => group buffer value_type group_buffers[total_num_groups][N + 1]; // tree->group_buffers->delete_buffer (extra space for sentinel) value_type * group_buffer_current_mins[total_num_groups]; // group_buffer_current_mins[i] is current start of group_buffers[i], end is group_buffers[i] + N // overall delete buffer value_type delete_buffer[delete_buffer_size + 1]; value_type * delete_buffer_current_min; // current start of delete_buffer value_type * delete_buffer_end; // end of delete_buffer comparator_type cmp; // insert buffer insert_heap_type insert_heap; // how many groups are active unsigned_type num_active_groups; // total size not counting insert_heap and delete_buffer size_type size_; private: void init(); void refill_delete_buffer(); unsigned_type refill_group_buffer(unsigned_type k); unsigned_type make_space_available(unsigned_type level); void empty_insert_heap(); value_type get_supremum() const { return cmp.min_value(); } //{ return group_buffers[0][KNN].key; } unsigned_type current_delete_buffer_size() const { return delete_buffer_end - delete_buffer_current_min; } unsigned_type current_group_buffer_size(unsigned_type i) const { return &(group_buffers[i][N]) - group_buffer_current_mins[i]; } public: //! \brief Constructs external priority queue object //! \param pool_ pool of blocks that will be used //! for data writing and prefetching for the disk<->memory transfers //! happening in the priority queue. Larger pool size //! helps to speed up operations. priority_queue(pool_type & pool_); //! \brief Constructs external priority queue object //! \param p_pool_ pool of blocks that will be used //! for data prefetching for the disk<->memory transfers //! happening in the priority queue. Larger pool size //! helps to speed up operations. //! \param w_pool_ pool of blocks that will be used //! for writing data for the memory<->disk transfers //! happening in the priority queue. Larger pool size //! helps to speed up operations. _STXXL_DEPRECATED(priority_queue(prefetch_pool & p_pool_, write_pool & w_pool_)); //! \brief Constructs external priority queue object //! \param p_pool_mem memory (in bytes) for prefetch pool that will be used //! for data prefetching for the disk<->memory transfers //! happening in the priority queue. Larger pool size //! helps to speed up operations. //! \param w_pool_mem memory (in bytes) for buffered write pool that will be used //! for writing data for the memory<->disk transfers //! happening in the priority queue. Larger pool size //! helps to speed up operations. priority_queue(unsigned_type p_pool_mem, unsigned_type w_pool_mem); //! \brief swap this priority queue with another one //! Implementation correctness is questionable. void swap(priority_queue & obj) { //swap_1D_arrays(int_mergers,obj.int_mergers,num_int_groups); // does not work in g++ 3.4.3 :( bug? for (unsigned_type i = 0; i < num_int_groups; ++i) std::swap(int_mergers[i], obj.int_mergers[i]); //std::swap(pool,obj.pool); //std::swap(pool_owned, obj.pool_owned); std::swap(ext_mergers, obj.ext_mergers); for (unsigned_type i1 = 0; i1 < total_num_groups; ++i1) for (unsigned_type i2 = 0; i2 < (N + 1); ++i2) std::swap(group_buffers[i1][i2], obj.group_buffers[i1][i2]); swap_1D_arrays(group_buffer_current_mins, obj.group_buffer_current_mins, total_num_groups); swap_1D_arrays(delete_buffer, obj.delete_buffer, delete_buffer_size + 1); std::swap(delete_buffer_current_min, obj.delete_buffer_current_min); std::swap(delete_buffer_end, obj.delete_buffer_end); std::swap(cmp, obj.cmp); std::swap(insert_heap, obj.insert_heap); std::swap(num_active_groups, obj.num_active_groups); std::swap(size_, obj.size_); } virtual ~priority_queue(); //! \brief Returns number of elements contained //! \return number of elements contained size_type size() const; //! \brief Returns true if queue has no elements //! \return \b true if queue has no elements, \b false otherwise bool empty() const { return (size() == 0); } //! \brief Returns "largest" element //! //! Returns a const reference to the element at the //! top of the priority_queue. The element at the top is //! guaranteed to be the largest element in the \b priority queue, //! as determined by the comparison function \b Config_::comparator_type //! (the same as the second parameter of PRIORITY_QUEUE_GENERATOR utility //! class). That is, //! for every other element \b x in the priority_queue, //! \b Config_::comparator_type(Q.top(), x) is false. //! Precondition: \c empty() is false. const value_type & top() const; //! \brief Removes the element at the top //! //! Removes the element at the top of the priority_queue, that //! is, the largest element in the \b priority_queue. //! Precondition: \c empty() is \b false. //! Postcondition: \c size() will be decremented by 1. void pop(); //! \brief Inserts x into the priority_queue. //! //! Inserts x into the priority_queue. Postcondition: //! \c size() will be incremented by 1. void push(const value_type & obj); //! \brief Returns number of bytes consumed by //! the \b priority_queue //! \brief number of bytes consumed by the \b priority_queue from //! the internal memory not including pools (see the constructor) unsigned_type mem_cons() const { unsigned_type dynam_alloc_mem = 0; //dynam_alloc_mem += w_pool.mem_cons(); //dynam_alloc_mem += p_pool.mem_cons(); for (int i = 0; i < num_int_groups; ++i) dynam_alloc_mem += int_mergers[i].mem_cons(); for (int i = 0; i < num_ext_groups; ++i) dynam_alloc_mem += ext_mergers[i].mem_cons(); return (sizeof(*this) + sizeof(ext_merger_type) * num_ext_groups + dynam_alloc_mem); } }; template inline typename priority_queue::size_type priority_queue::size() const { return size_ + insert_heap.size() - 1 + (delete_buffer_end - delete_buffer_current_min); } template inline const typename priority_queue::value_type & priority_queue::top() const { assert(!insert_heap.empty()); const typename priority_queue::value_type & t = insert_heap.top(); if (/*(!insert_heap.empty()) && */ cmp(*delete_buffer_current_min, t)) return t; else return *delete_buffer_current_min; } template inline void priority_queue::pop() { //STXXL_VERBOSE1("priority_queue::pop()"); assert(!insert_heap.empty()); if (/*(!insert_heap.empty()) && */ cmp(*delete_buffer_current_min, insert_heap.top())) insert_heap.pop(); else { assert(delete_buffer_current_min < delete_buffer_end); ++delete_buffer_current_min; if (delete_buffer_current_min == delete_buffer_end) refill_delete_buffer(); } } template inline void priority_queue::push(const value_type & obj) { //STXXL_VERBOSE3("priority_queue::push("<< obj <<")"); assert(int_mergers->not_sentinel(obj)); if (insert_heap.size() == N + 1) empty_insert_heap(); assert(!insert_heap.empty()); insert_heap.push(obj); } //////////////////////////////////////////////////////////////// template priority_queue::priority_queue(pool_type & pool_) : pool(&pool_), pool_owned(false), delete_buffer_end(delete_buffer + delete_buffer_size), insert_heap(N + 2), num_active_groups(0), size_(0) { STXXL_VERBOSE2("priority_queue::priority_queue(pool)"); init(); } // DEPRECATED template priority_queue::priority_queue(prefetch_pool & p_pool_, write_pool & w_pool_) : pool(new pool_type(p_pool_, w_pool_)), pool_owned(true), delete_buffer_end(delete_buffer + delete_buffer_size), insert_heap(N + 2), num_active_groups(0), size_(0) { STXXL_VERBOSE2("priority_queue::priority_queue(p_pool, w_pool)"); init(); } template priority_queue::priority_queue(unsigned_type p_pool_mem, unsigned_type w_pool_mem) : pool(new pool_type(p_pool_mem / BlockSize, w_pool_mem / BlockSize)), pool_owned(true), delete_buffer_end(delete_buffer + delete_buffer_size), insert_heap(N + 2), num_active_groups(0), size_(0) { STXXL_VERBOSE2("priority_queue::priority_queue(pool sizes)"); init(); } template void priority_queue::init() { assert(!cmp(cmp.min_value(), cmp.min_value())); // verify strict weak ordering ext_mergers = new ext_merger_type[num_ext_groups]; for (unsigned_type j = 0; j < num_ext_groups; ++j) ext_mergers[j].set_pool(pool); value_type sentinel = cmp.min_value(); insert_heap.push(sentinel); // always keep the sentinel delete_buffer[delete_buffer_size] = sentinel; // sentinel delete_buffer_current_min = delete_buffer_end; // empty for (unsigned_type i = 0; i < total_num_groups; i++) { group_buffers[i][N] = sentinel; // sentinel group_buffer_current_mins[i] = &(group_buffers[i][N]); // empty } } template priority_queue::~priority_queue() { STXXL_VERBOSE2("priority_queue::~priority_queue()"); if (pool_owned) delete pool; delete[] ext_mergers; } //--------------------- Buffer refilling ------------------------------- // refill group_buffers[j] and return number of elements found template unsigned_type priority_queue::refill_group_buffer(unsigned_type group) { STXXL_VERBOSE2("priority_queue::refill_group_buffer(" << group << ")"); value_type * target; unsigned_type length; size_type group_size = (group < num_int_groups) ? int_mergers[group].size() : ext_mergers[group - num_int_groups].size(); //elements left in segments unsigned_type left_elements = group_buffers[group] + N - group_buffer_current_mins[group]; //elements left in target buffer if (group_size + left_elements >= size_type(N)) { // buffer will be filled completely target = group_buffers[group]; length = N - left_elements; } else { target = group_buffers[group] + N - group_size - left_elements; length = group_size; } if (length > 0) { // shift remaininig elements to front memmove(target, group_buffer_current_mins[group], left_elements * sizeof(value_type)); group_buffer_current_mins[group] = target; // fill remaining space from group if (group < num_int_groups) int_mergers[group].multi_merge(target + left_elements, length); else ext_mergers[group - num_int_groups].multi_merge( target + left_elements, target + left_elements + length); } //STXXL_MSG(length + left_elements); //std::copy(target,target + length + left_elements,std::ostream_iterator(std::cout, "\n")); #if STXXL_CHECK_ORDER_IN_SORTS priority_queue_local::invert_order inv_cmp(cmp); if (!stxxl::is_sorted(group_buffer_current_mins[group], group_buffers[group] + N, inv_cmp)) { STXXL_VERBOSE2("length: " << length << " left_elements: " << left_elements); for (value_type * v = group_buffer_current_mins[group] + 1; v < group_buffer_current_mins[group] + left_elements; ++v) { if (inv_cmp(*v, *(v - 1))) { STXXL_MSG("Error in buffer " << group << " at position " << (v - group_buffer_current_mins[group] - 1) << "/" << (v - group_buffer_current_mins[group]) << " " << *(v - 2) << " " << *(v - 1) << " " << *v << " " << *(v + 1)); } } assert(false); } #endif return length + left_elements; } template void priority_queue::refill_delete_buffer() { STXXL_VERBOSE2("priority_queue::refill_delete_buffer()"); size_type total_group_size = 0; //num_active_groups is <= 4 for (int i = num_active_groups - 1; i >= 0; i--) { if ((group_buffers[i] + N) - group_buffer_current_mins[i] < delete_buffer_size) { unsigned_type length = refill_group_buffer(i); // max active level dry now? if (length == 0 && unsigned(i) == num_active_groups - 1) --num_active_groups; total_group_size += length; } else total_group_size += delete_buffer_size; // actually only a sufficient lower bound } unsigned_type length; if (total_group_size >= delete_buffer_size) // buffer can be filled completely { length = delete_buffer_size; // amount to be copied size_ -= size_type(delete_buffer_size); // amount left in group_buffers } else { length = total_group_size; assert(size_ == size_type(length)); // trees and group_buffers get empty size_ = 0; } priority_queue_local::invert_order inv_cmp(cmp); // now call simplified refill routines // which can make the assumption that // they find all they are asked in the buffers delete_buffer_current_min = delete_buffer_end - length; STXXL_VERBOSE2("Active groups = " << num_active_groups); switch (num_active_groups) { case 0: break; case 1: std::copy(group_buffer_current_mins[0], group_buffer_current_mins[0] + length, delete_buffer_current_min); group_buffer_current_mins[0] += length; break; case 2: #if STXXL_PARALLEL && STXXL_PARALLEL_PQ_MULTIWAY_MERGE_DELETE_BUFFER { std::pair seqs[2] = { std::make_pair(group_buffer_current_mins[0], group_buffers[0] + N), std::make_pair(group_buffer_current_mins[1], group_buffers[1] + N) }; parallel::multiway_merge_sentinel(seqs, seqs + 2, delete_buffer_current_min, inv_cmp, length); //sequence iterators are progressed appropriately group_buffer_current_mins[0] = seqs[0].first; group_buffer_current_mins[1] = seqs[1].first; } #else priority_queue_local::merge_iterator( group_buffer_current_mins[0], group_buffer_current_mins[1], delete_buffer_current_min, length, cmp); #endif break; case 3: #if STXXL_PARALLEL && STXXL_PARALLEL_PQ_MULTIWAY_MERGE_DELETE_BUFFER { std::pair seqs[3] = { std::make_pair(group_buffer_current_mins[0], group_buffers[0] + N), std::make_pair(group_buffer_current_mins[1], group_buffers[1] + N), std::make_pair(group_buffer_current_mins[2], group_buffers[2] + N) }; parallel::multiway_merge_sentinel(seqs, seqs + 3, delete_buffer_current_min, inv_cmp, length); //sequence iterators are progressed appropriately group_buffer_current_mins[0] = seqs[0].first; group_buffer_current_mins[1] = seqs[1].first; group_buffer_current_mins[2] = seqs[2].first; } #else priority_queue_local::merge3_iterator( group_buffer_current_mins[0], group_buffer_current_mins[1], group_buffer_current_mins[2], delete_buffer_current_min, length, cmp); #endif break; case 4: #if STXXL_PARALLEL && STXXL_PARALLEL_PQ_MULTIWAY_MERGE_DELETE_BUFFER { std::pair seqs[4] = { std::make_pair(group_buffer_current_mins[0], group_buffers[0] + N), std::make_pair(group_buffer_current_mins[1], group_buffers[1] + N), std::make_pair(group_buffer_current_mins[2], group_buffers[2] + N), std::make_pair(group_buffer_current_mins[3], group_buffers[3] + N) }; parallel::multiway_merge_sentinel(seqs, seqs + 4, delete_buffer_current_min, inv_cmp, length); //sequence iterators are progressed appropriately group_buffer_current_mins[0] = seqs[0].first; group_buffer_current_mins[1] = seqs[1].first; group_buffer_current_mins[2] = seqs[2].first; group_buffer_current_mins[3] = seqs[3].first; } #else priority_queue_local::merge4_iterator( group_buffer_current_mins[0], group_buffer_current_mins[1], group_buffer_current_mins[2], group_buffer_current_mins[3], delete_buffer_current_min, length, cmp); //side effect free #endif break; default: STXXL_THROW(std::runtime_error, "priority_queue<...>::refill_delete_buffer()", "Overflow! The number of buffers on 2nd level in stxxl::priority_queue is currently limited to 4"); } #if STXXL_CHECK_ORDER_IN_SORTS if (!stxxl::is_sorted(delete_buffer_current_min, delete_buffer_end, inv_cmp)) { for (value_type * v = delete_buffer_current_min + 1; v < delete_buffer_end; ++v) { if (inv_cmp(*v, *(v - 1))) { STXXL_MSG("Error at position " << (v - delete_buffer_current_min - 1) << "/" << (v - delete_buffer_current_min) << " " << *(v - 1) << " " << *v); } } assert(false); } #endif //std::copy(delete_buffer_current_min,delete_buffer_current_min + length,std::ostream_iterator(std::cout, "\n")); } //-------------------------------------------------------------------- // check if space is available on level k and // empty this level if necessary leading to a recursive call. // return the level where space was finally available template unsigned_type priority_queue::make_space_available(unsigned_type level) { STXXL_VERBOSE2("priority_queue::make_space_available(" << level << ")"); unsigned_type finalLevel; assert(level < total_num_groups); assert(level <= num_active_groups); if (level == num_active_groups) ++num_active_groups; const bool spaceIsAvailable_ = (level < num_int_groups) ? int_mergers[level].is_space_available() : ((level == total_num_groups - 1) ? true : (ext_mergers[level - num_int_groups].is_space_available())); if (spaceIsAvailable_) { finalLevel = level; } else { finalLevel = make_space_available(level + 1); if (level < num_int_groups - 1) // from internal to internal tree { unsigned_type segmentSize = int_mergers[level].size(); value_type * newSegment = new value_type[segmentSize + 1]; int_mergers[level].multi_merge(newSegment, segmentSize); // empty this level newSegment[segmentSize] = delete_buffer[delete_buffer_size]; // sentinel // for queues where size << #inserts // it might make sense to stay in this level if // segmentSize < alpha * KNN * k^level for some alpha < 1 int_mergers[level + 1].insert_segment(newSegment, segmentSize); } else { if (level == num_int_groups - 1) // from internal to external tree { const unsigned_type segmentSize = int_mergers[num_int_groups - 1].size(); STXXL_VERBOSE1("Inserting segment into first level external: " << level << " " << segmentSize); ext_mergers[0].insert_segment(int_mergers[num_int_groups - 1], segmentSize); } else // from external to external tree { const size_type segmentSize = ext_mergers[level - num_int_groups].size(); STXXL_VERBOSE1("Inserting segment into second level external: " << level << " " << segmentSize); ext_mergers[level - num_int_groups + 1].insert_segment(ext_mergers[level - num_int_groups], segmentSize); } } } return finalLevel; } // empty the insert heap into the main data structure template void priority_queue::empty_insert_heap() { STXXL_VERBOSE2("priority_queue::empty_insert_heap()"); assert(insert_heap.size() == (N + 1)); const value_type sup = get_supremum(); // build new segment value_type * newSegment = new value_type[N + 1]; value_type * newPos = newSegment; // put the new data there for now //insert_heap.sortTo(newSegment); value_type * SortTo = newSegment; insert_heap.sort_to(SortTo); SortTo = newSegment + N; insert_heap.clear(); insert_heap.push(*SortTo); assert(insert_heap.size() == 1); newSegment[N] = sup; // sentinel // copy the delete_buffer and group_buffers[0] to temporary storage // (the temporary can be eliminated using some dirty tricks) const unsigned_type tempSize = N + delete_buffer_size; value_type temp[tempSize + 1]; unsigned_type sz1 = current_delete_buffer_size(); unsigned_type sz2 = current_group_buffer_size(0); value_type * pos = temp + tempSize - sz1 - sz2; std::copy(delete_buffer_current_min, delete_buffer_current_min + sz1, pos); std::copy(group_buffer_current_mins[0], group_buffer_current_mins[0] + sz2, pos + sz1); temp[tempSize] = sup; // sentinel // refill delete_buffer // (using more complicated code it could be made somewhat fuller // in certain circumstances) priority_queue_local::merge_iterator(pos, newPos, delete_buffer_current_min, sz1, cmp); // refill group_buffers[0] // (as above we might want to take the opportunity // to make group_buffers[0] fuller) priority_queue_local::merge_iterator(pos, newPos, group_buffer_current_mins[0], sz2, cmp); // merge the rest to the new segment // note that merge exactly trips into the footsteps // of itself priority_queue_local::merge_iterator(pos, newPos, newSegment, N, cmp); // and insert it unsigned_type freeLevel = make_space_available(0); assert(freeLevel == 0 || int_mergers[0].size() == 0); int_mergers[0].insert_segment(newSegment, N); // get rid of invalid level 2 buffers // by inserting them into tree 0 (which is almost empty in this case) if (freeLevel > 0) { for (int_type i = freeLevel; i >= 0; i--) { // reverse order not needed // but would allow immediate refill newSegment = new value_type[current_group_buffer_size(i) + 1]; // with sentinel std::copy(group_buffer_current_mins[i], group_buffer_current_mins[i] + current_group_buffer_size(i) + 1, newSegment); int_mergers[0].insert_segment(newSegment, current_group_buffer_size(i)); group_buffer_current_mins[i] = group_buffers[i] + N; // empty } } // update size size_ += size_type(N); // special case if the tree was empty before if (delete_buffer_current_min == delete_buffer_end) refill_delete_buffer(); } namespace priority_queue_local { struct Parameters_for_priority_queue_not_found_Increase_IntM { enum { fits = false }; typedef Parameters_for_priority_queue_not_found_Increase_IntM result; }; struct dummy { enum { fits = false }; typedef dummy result; }; template struct find_B_m { typedef find_B_m Self; enum { k = IntM_ / B_, // number of blocks that fit into M element_size = E_, // element size IntM = IntM_, B = B_, // block size m = m_, // number of blocks fitting into buffers c = k - m_, // memory occ. by block must be at least 10 times larger than size of ext sequence // && satisfy memory req && if we have two ext mergers their degree must be at least 64=m/2 fits = c > 10 && ((k - m) * (m) * (m * B / (element_size * 4 * 1024))) >= MaxS_ && ((MaxS_ < ((k - m) * m / (2 * element_size)) * 1024) || m >= 128), step = 1 }; typedef typename find_B_m= k - step)>::result candidate1; typedef typename find_B_m::result candidate2; typedef typename IF::result>::result result; }; // specialization for the case when no valid parameters are found template struct find_B_m { enum { fits = false }; typedef Parameters_for_priority_queue_not_found_Increase_IntM result; }; // to speedup search template struct find_B_m { enum { fits = false }; typedef dummy result; }; // E_ size of element in bytes template struct find_settings { // start from block size (8*1024*1024) bytes typedef typename find_B_m::result result; }; struct Parameters_not_found_Try_to_change_the_Tune_parameter { typedef Parameters_not_found_Try_to_change_the_Tune_parameter result; }; template struct compute_N { typedef compute_N Self; enum { X = X_, AI = AI_, N = X / (AI * AI) // two stage internal }; typedef typename IF<(N >= CriticalSize_), Self, typename compute_N::result>::result result; }; template struct compute_N<1, X_, CriticalSize_> { typedef Parameters_not_found_Try_to_change_the_Tune_parameter result; }; } //! \} //! \addtogroup stlcont //! \{ //! \brief Priority queue type generator //! Implements a data structure from "Peter Sanders. Fast Priority Queues //! for Cached Memory. ALENEX'99" for external memory. //!
//! \tparam type of the contained objects (POD with no references to internal memory) //! \tparam the comparison type used to determine //! whether one element is smaller than another element. //! If Cmp_(x,y) is true, then x is smaller than y. The element //! returned by Q.top() is the largest element in the priority //! queue. That is, it has the property that, for every other //! element \b x in the priority queue, Cmp_(Q.top(), x) is false. //! Cmp_ must also provide min_value method, that returns value of type Tp_ that is //! smaller than any element of the queue \b x , i.e. Cmp_(Cmp_.min_value(),x) is //! always \b true .
//!
//! Example: comparison object for priority queue //! where \b top() returns the \b smallest contained integer: //! \verbatim //! struct CmpIntGreater //! { //! bool operator () (const int & a, const int & b) const { return a>b; } //! int min_value() const { return std::numeric_limits::max(); } //! }; //! \endverbatim //! Example: comparison object for priority queue //! where \b top() returns the \b largest contained integer: //! \verbatim //! struct CmpIntLess //! { //! bool operator () (const int & a, const int & b) const { return a::min(); } //! }; //! \endverbatim //! Note that Cmp_ must define strict weak ordering. //! (see what it is) //! - \c IntM_ upper limit for internal memory consumption in bytes. //! - \c MaxS_ upper limit for number of elements contained in the priority queue (in 1024 units). //! Example: if you are sure that priority queue contains no more than //! one million elements in a time, then the right parameter is (1000000/1024)= 976 . //! - \c Tune_ tuning parameter. Try to play with it if the code does not compile //! (larger than default values might help). Code does not compile //! if no suitable internal parameters were found for given IntM_ and MaxS_. //! It might also happen that given IntM_ is too small for given MaxS_, try larger values. //!
//! \c PRIORITY_QUEUE_GENERATOR is template meta program that searches //! for \b 7 configuration parameters of \b stxxl::priority_queue that both //! minimize internal memory consumption of the priority queue to //! match IntM_ and maximize performance of priority queue operations. //! Actual memory consumption might be larger (use //! \c stxxl::priority_queue::mem_cons() method to track it), since the search //! assumes rather optimistic schedule of push'es and pop'es for the //! estimation of the maximum memory consumption. To keep actual memory //! requirements low increase the value of MaxS_ parameter. //!
//! For functioning a priority queue object requires two pools of blocks //! (See constructor of \c priority_queue ). To construct \c \ block //! pools you might need \b block \b type that will be used by priority queue. //! Note that block's size and hence it's type is generated by //! the \c PRIORITY_QUEUE_GENERATOR in compile type from IntM_, MaxS_ and sizeof(Tp_) and //! not given directly by user as a template parameter. Block type can be extracted as //! \c PRIORITY_QUEUE_GENERATOR::result::block_type . //! For an example see p_queue.cpp . //! Configured priority queue type is available as \c PRIORITY_QUEUE_GENERATOR<>::result.

template class PRIORITY_QUEUE_GENERATOR { public: // actual calculation of B, m, k and element_size typedef typename priority_queue_local::find_settings::result settings; enum { B = settings::B, m = settings::m, X = B * (settings::k - m) / settings::element_size, // interpretation of result Buffer1Size = 32 // fixed }; // derivation of N, AI, AE typedef typename priority_queue_local::compute_N<(1 << Tune_), X, 4 * Buffer1Size>::result ComputeN; enum { N = ComputeN::N, AI = ComputeN::AI, AE = (m / 2 < 2) ? 2 : (m / 2) // at least 2 }; enum { // Estimation of maximum internal memory consumption (in bytes) EConsumption = X * settings::element_size + settings::B * AE + ((MaxS_ / X) / AE) * settings::B * 1024 }; /* unsigned BufferSize1_ = 32, // equalize procedure call overheads etc. unsigned N_ = 512, // bandwidth unsigned IntKMAX_ = 64, // maximal arity for internal mergers unsigned IntLevels_ = 4, unsigned BlockSize_ = (2*1024*1024), unsigned ExtKMAX_ = 64, // maximal arity for external mergers unsigned ExtLevels_ = 2, */ typedef priority_queue > result; }; //! \} __STXXL_END_NAMESPACE namespace std { template void swap(stxxl::priority_queue & a, stxxl::priority_queue & b) { a.swap(b); } } #endif // !STXXL_PRIORITY_QUEUE_HEADER // vim: et:ts=4:sw=4 stxxl-1.3.1/include/stxxl/bits/containers/stack.h0000644000175000017500000007025511535500414021712 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/containers/stack.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2003-2004 Roman Dementiev * Copyright (C) 2009, 2010 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_STACK_HEADER #define STXXL_STACK_HEADER #include #include #include #include #include #include #include #include #include #include #include __STXXL_BEGIN_NAMESPACE //! \addtogroup stlcontinternals //! \{ template struct stack_config_generator { typedef ValTp value_type; enum { blocks_per_page = BlocksPerPage }; typedef AllocStr alloc_strategy; enum { block_size = BlkSz }; typedef SzTp size_type; }; //! \brief External stack container //! Conservative implementation. Fits best if your access pattern consists of irregularly mixed //! push'es and pop's. //! For semantics of the methods see documentation of the STL \c std::stack.
//! To gain full bandwidth of disks \c Config_::BlocksPerPage must >= number of disks
//! \internal template class normal_stack : private noncopyable { public: typedef Config_ cfg; typedef typename cfg::value_type value_type; typedef typename cfg::alloc_strategy alloc_strategy_type; typedef typename cfg::size_type size_type; enum { blocks_per_page = cfg::blocks_per_page, block_size = cfg::block_size }; typedef typed_block block_type; typedef BID bid_type; private: size_type size_; unsigned_type cache_offset; value_type * current_element; simple_vector cache; typename simple_vector::iterator front_page; typename simple_vector::iterator back_page; std::vector bids; alloc_strategy_type alloc_strategy; public: normal_stack() : size_(0), cache_offset(0), current_element(NULL), cache(blocks_per_page * 2), front_page(cache.begin() + blocks_per_page), back_page(cache.begin()), bids(0) { bids.reserve(blocks_per_page); } void swap(normal_stack & obj) { std::swap(size_, obj.size_); std::swap(cache_offset, obj.cache_offset); std::swap(current_element, obj.current_element); std::swap(cache, obj.cache); std::swap(front_page, obj.front_page); std::swap(back_page, obj.back_page); std::swap(bids, obj.bids); std::swap(alloc_strategy, obj.alloc_strategy); } //! \brief Construction from a stack //! \param stack_ stack object (could be external or internal, important is that it must //! have a copy constructor, \c top() and \c pop() methods ) template normal_stack(const stack_type & stack_) : size_(0), cache_offset(0), current_element(NULL), cache(blocks_per_page * 2), front_page(cache.begin() + blocks_per_page), back_page(cache.begin()), bids(0) { bids.reserve(blocks_per_page); stack_type stack_copy = stack_; const size_type sz = stack_copy.size(); size_type i; std::vector tmp(sz); for (i = 0; i < sz; ++i) { tmp[sz - i - 1] = stack_copy.top(); stack_copy.pop(); } for (i = 0; i < sz; ++i) this->push(tmp[i]); } virtual ~normal_stack() { STXXL_VERBOSE(STXXL_PRETTY_FUNCTION_NAME); block_manager::get_instance()->delete_blocks(bids.begin(), bids.end()); } size_type size() const { return size_; } bool empty() const { return (!size_); } value_type & top() { assert(size_ > 0); return (*current_element); } const value_type & top() const { assert(size_ > 0); return (*current_element); } void push(const value_type & val) { assert(cache_offset <= 2 * blocks_per_page * block_type::size); //assert(cache_offset >= 0); if (cache_offset == 2 * blocks_per_page * block_type::size) // cache overflow { STXXL_VERBOSE2("growing, size: " << size_); bids.resize(bids.size() + blocks_per_page); typename std::vector::iterator cur_bid = bids.end() - blocks_per_page; block_manager::get_instance()->new_blocks(alloc_strategy, cur_bid, bids.end(), cur_bid - bids.begin()); simple_vector requests(blocks_per_page); for (int i = 0; i < blocks_per_page; ++i, ++cur_bid) { requests[i] = (back_page + i)->write(*cur_bid); } std::swap(back_page, front_page); bids.reserve(bids.size() + blocks_per_page); cache_offset = blocks_per_page * block_type::size + 1; current_element = &((*front_page)[0]); ++size_; wait_all(requests.begin(), blocks_per_page); *current_element = val; return; } current_element = element(cache_offset); *current_element = val; ++size_; ++cache_offset; } void pop() { assert(cache_offset <= 2 * blocks_per_page * block_type::size); assert(cache_offset > 0); assert(size_ > 0); if (cache_offset == 1 && bids.size() >= blocks_per_page) { STXXL_VERBOSE2("shrinking, size: " << size_); simple_vector requests(blocks_per_page); { typename std::vector::const_iterator cur_bid = bids.end(); for (int i = blocks_per_page - 1; i >= 0; --i) { requests[i] = (front_page + i)->read(*(--cur_bid)); } } std::swap(front_page, back_page); cache_offset = blocks_per_page * block_type::size; --size_; current_element = &((*(back_page + (blocks_per_page - 1)))[block_type::size - 1]); wait_all(requests.begin(), blocks_per_page); block_manager::get_instance()->delete_blocks(bids.end() - blocks_per_page, bids.end()); bids.resize(bids.size() - blocks_per_page); return; } --size_; current_element = element((--cache_offset) - 1); } private: value_type * element(unsigned_type offset) { if (offset < blocks_per_page * block_type::size) return &((*(back_page + offset / block_type::size))[offset % block_type::size]); unsigned_type unbiased_offset = offset - blocks_per_page * block_type::size; return &((*(front_page + unbiased_offset / block_type::size))[unbiased_offset % block_type::size]); } }; //! \brief Efficient implementation that uses prefetching and overlapping using internal buffers //! Use it if your access pattern consists of many repeated push'es and pop's //! For semantics of the methods see documentation of the STL \c std::stack. //! \warning The amortized complexity of operation is not O(1/DB), rather O(DB) template class grow_shrink_stack : private noncopyable { public: typedef Config_ cfg; typedef typename cfg::value_type value_type; typedef typename cfg::alloc_strategy alloc_strategy_type; typedef typename cfg::size_type size_type; enum { blocks_per_page = cfg::blocks_per_page, block_size = cfg::block_size, }; typedef typed_block block_type; typedef BID bid_type; private: size_type size_; unsigned_type cache_offset; value_type * current_element; simple_vector cache; typename simple_vector::iterator cache_buffers; typename simple_vector::iterator overlap_buffers; simple_vector requests; std::vector bids; alloc_strategy_type alloc_strategy; public: grow_shrink_stack() : size_(0), cache_offset(0), current_element(NULL), cache(blocks_per_page * 2), cache_buffers(cache.begin()), overlap_buffers(cache.begin() + blocks_per_page), requests(blocks_per_page), bids(0) { bids.reserve(blocks_per_page); } void swap(grow_shrink_stack & obj) { std::swap(size_, obj.size_); std::swap(cache_offset, obj.cache_offset); std::swap(current_element, obj.current_element); std::swap(cache, obj.cache); std::swap(cache_buffers, obj.cache_buffers); std::swap(overlap_buffers, obj.overlap_buffers); std::swap(requests, obj.requests); std::swap(bids, obj.bids); std::swap(alloc_strategy, obj.alloc_strategy); } //! \brief Construction from a stack //! \param stack_ stack object (could be external or internal, important is that it must //! have a copy constructor, \c top() and \c pop() methods ) template grow_shrink_stack(const stack_type & stack_) : size_(0), cache_offset(0), current_element(NULL), cache(blocks_per_page * 2), cache_buffers(cache.begin()), overlap_buffers(cache.begin() + blocks_per_page), requests(blocks_per_page), bids(0) { bids.reserve(blocks_per_page); stack_type stack_copy = stack_; const size_type sz = stack_copy.size(); size_type i; std::vector tmp(sz); for (i = 0; i < sz; ++i) { tmp[sz - i - 1] = stack_copy.top(); stack_copy.pop(); } for (i = 0; i < sz; ++i) this->push(tmp[i]); } virtual ~grow_shrink_stack() { STXXL_VERBOSE(STXXL_PRETTY_FUNCTION_NAME); try { if (requests[0].get()) wait_all(requests.begin(), blocks_per_page); } catch (const io_error & ex) { } block_manager::get_instance()->delete_blocks(bids.begin(), bids.end()); } size_type size() const { return size_; } bool empty() const { return (!size_); } value_type & top() { assert(size_ > 0); return (*current_element); } const value_type & top() const { assert(size_ > 0); return (*current_element); } void push(const value_type & val) { assert(cache_offset <= blocks_per_page * block_type::size); //assert(cache_offset >= 0); if (cache_offset == blocks_per_page * block_type::size) // cache overflow { STXXL_VERBOSE2("growing, size: " << size_); bids.resize(bids.size() + blocks_per_page); typename std::vector::iterator cur_bid = bids.end() - blocks_per_page; block_manager::get_instance()->new_blocks(alloc_strategy, cur_bid, bids.end(), cur_bid - bids.begin()); for (int i = 0; i < blocks_per_page; ++i, ++cur_bid) { if (requests[i].get()) requests[i]->wait(); requests[i] = (cache_buffers + i)->write(*cur_bid); } std::swap(cache_buffers, overlap_buffers); bids.reserve(bids.size() + blocks_per_page); cache_offset = 1; current_element = &((*cache_buffers)[0]); ++size_; *current_element = val; return; } current_element = &((*(cache_buffers + cache_offset / block_type::size))[cache_offset % block_type::size]); *current_element = val; ++size_; ++cache_offset; } void pop() { assert(cache_offset <= blocks_per_page * block_type::size); assert(cache_offset > 0); assert(size_ > 0); if (cache_offset == 1 && bids.size() >= blocks_per_page) { STXXL_VERBOSE2("shrinking, size: " << size_); if (requests[0].get()) wait_all(requests.begin(), blocks_per_page); std::swap(cache_buffers, overlap_buffers); if (bids.size() > blocks_per_page) { STXXL_VERBOSE2("prefetching, size: " << size_); typename std::vector::const_iterator cur_bid = bids.end() - blocks_per_page; for (int i = blocks_per_page - 1; i >= 0; --i) requests[i] = (overlap_buffers + i)->read(*(--cur_bid)); } block_manager::get_instance()->delete_blocks(bids.end() - blocks_per_page, bids.end()); bids.resize(bids.size() - blocks_per_page); cache_offset = blocks_per_page * block_type::size; --size_; current_element = &((*(cache_buffers + (blocks_per_page - 1)))[block_type::size - 1]); return; } --size_; unsigned_type cur_offset = (--cache_offset) - 1; current_element = &((*(cache_buffers + cur_offset / block_type::size))[cur_offset % block_type::size]); } }; //! \brief Efficient implementation that uses prefetching and overlapping using (shared) buffers pools //! \warning This is a single buffer stack! Each direction change (push() followed by pop() or vice versa) may cause one I/O. template class grow_shrink_stack2 : private noncopyable { public: typedef Config_ cfg; typedef typename cfg::value_type value_type; typedef typename cfg::alloc_strategy alloc_strategy_type; typedef typename cfg::size_type size_type; enum { blocks_per_page = cfg::blocks_per_page, // stack of this type has only one page block_size = cfg::block_size, }; typedef typed_block block_type; typedef BID bid_type; private: typedef read_write_pool pool_type; size_type size_; unsigned_type cache_offset; block_type * cache; std::vector bids; alloc_strategy_type alloc_strategy; unsigned_type pref_aggr; pool_type * owned_pool; pool_type * pool; public: //! \brief Constructs stack //! \param pool_ block write/prefetch pool //! \param prefetch_aggressiveness number of blocks that will be used from prefetch pool grow_shrink_stack2( pool_type & pool_, unsigned_type prefetch_aggressiveness = 0) : size_(0), cache_offset(0), cache(new block_type), pref_aggr(prefetch_aggressiveness), owned_pool(NULL), pool(&pool_) { STXXL_VERBOSE2("grow_shrink_stack2::grow_shrink_stack2(...)"); } //! \brief Constructs stack //! \param p_pool_ prefetch pool, that will be used for block prefetching //! \param w_pool_ write pool, that will be used for block writing //! \param prefetch_aggressiveness number of blocks that will be used from prefetch pool _STXXL_DEPRECATED(grow_shrink_stack2( prefetch_pool & p_pool_, write_pool & w_pool_, unsigned_type prefetch_aggressiveness = 0)) : size_(0), cache_offset(0), cache(new block_type), pref_aggr(prefetch_aggressiveness), owned_pool(new pool_type(p_pool_, w_pool_)), pool(owned_pool) { STXXL_VERBOSE2("grow_shrink_stack2::grow_shrink_stack2(...)"); } void swap(grow_shrink_stack2 & obj) { std::swap(size_, obj.size_); std::swap(cache_offset, obj.cache_offset); std::swap(cache, obj.cache); std::swap(bids, obj.bids); std::swap(alloc_strategy, obj.alloc_strategy); std::swap(pref_aggr, obj.pref_aggr); std::swap(owned_pool, obj.owned_pool); std::swap(pool, obj.pool); } virtual ~grow_shrink_stack2() { try { STXXL_VERBOSE2("grow_shrink_stack2::~grow_shrink_stack2()"); const int_type bids_size = bids.size(); const int_type last_pref = STXXL_MAX(int_type(bids_size) - int_type(pref_aggr), (int_type)0); int_type i; for (i = bids_size - 1; i >= last_pref; --i) { // clean the prefetch buffer pool->invalidate(bids[i]); } typename std::vector::iterator cur = bids.begin(); typename std::vector::const_iterator end = bids.end(); for ( ; cur != end; ++cur) { // FIXME: read_write_pool needs something like cancel_write(bid) block_type * b = NULL; // w_pool.steal(*cur); if (b) { pool->add(cache); // return buffer cache = b; } } delete cache; } catch (const io_error & ex) { } block_manager::get_instance()->delete_blocks(bids.begin(), bids.end()); delete owned_pool; } size_type size() const { return size_; } bool empty() const { return (!size_); } void push(const value_type & val) { STXXL_VERBOSE3("grow_shrink_stack2::push(" << val << ")"); assert(cache_offset <= block_type::size); if (cache_offset == block_type::size) { STXXL_VERBOSE2("grow_shrink_stack2::push(" << val << ") growing, size: " << size_); bids.resize(bids.size() + 1); typename std::vector::iterator cur_bid = bids.end() - 1; block_manager::get_instance()->new_blocks(alloc_strategy, cur_bid, bids.end(), cur_bid - bids.begin()); pool->write(cache, bids.back()); cache = pool->steal(); const int_type bids_size = bids.size(); const int_type last_pref = STXXL_MAX(int_type(bids_size) - int_type(pref_aggr) - 1, (int_type)0); for (int_type i = bids_size - 2; i >= last_pref; --i) { // clean prefetch buffers pool->invalidate(bids[i]); } cache_offset = 0; } (*cache)[cache_offset] = val; ++size_; ++cache_offset; assert(cache_offset > 0); assert(cache_offset <= block_type::size); } value_type & top() { assert(size_ > 0); assert(cache_offset > 0); assert(cache_offset <= block_type::size); return (*cache)[cache_offset - 1]; } const value_type & top() const { assert(size_ > 0); assert(cache_offset > 0); assert(cache_offset <= block_type::size); return (*cache)[cache_offset - 1]; } void pop() { STXXL_VERBOSE3("grow_shrink_stack2::pop()"); assert(size_ > 0); assert(cache_offset > 0); assert(cache_offset <= block_type::size); if (cache_offset == 1 && (!bids.empty())) { STXXL_VERBOSE2("grow_shrink_stack2::pop() shrinking, size = " << size_); bid_type last_block = bids.back(); bids.pop_back(); pool->read(cache, last_block)->wait(); block_manager::get_instance()->delete_block(last_block); rehint(); cache_offset = block_type::size + 1; } --cache_offset; --size_; } //! \brief Sets level of prefetch aggressiveness (number //! of blocks from the prefetch pool used for prefetching) //! \param new_p new value for the prefetch aggressiveness void set_prefetch_aggr(unsigned_type new_p) { if (pref_aggr > new_p) { const int_type bids_size = bids.size(); const int_type last_pref = STXXL_MAX(int_type(bids_size) - int_type(pref_aggr), (int_type)0); for (int_type i = bids_size - new_p - 1; i >= last_pref; --i) { // clean prefetch buffers pool->invalidate(bids[i]); } } pref_aggr = new_p; rehint(); } //! \brief Returns number of blocks used for prefetching unsigned_type get_prefetch_aggr() const { return pref_aggr; } private: //! \brief hint the last pref_aggr external blocks void rehint() { const int_type bids_size = bids.size(); const int_type last_pref = STXXL_MAX(int_type(bids_size) - int_type(pref_aggr), (int_type)0); for (int_type i = bids_size - 1; i >= last_pref; --i) { pool->hint(bids[i]); // prefetch } } }; //! \brief A stack that migrates from internal memory to external when its size exceeds a certain threshold //! For semantics of the methods see documentation of the STL \c std::stack. template class migrating_stack : private noncopyable { public: typedef typename ExternalStack::cfg cfg; typedef typename cfg::value_type value_type; typedef typename cfg::size_type size_type; enum { blocks_per_page = cfg::blocks_per_page, block_size = cfg::block_size }; typedef InternalStack int_stack_type; typedef ExternalStack ext_stack_type; private: enum { critical_size = CritSize }; int_stack_type * int_impl; ext_stack_type * ext_impl; // not implemented yet template migrating_stack(const stack_type & stack_); public: migrating_stack() : int_impl(new int_stack_type()), ext_impl(NULL) { } void swap(migrating_stack & obj) { std::swap(int_impl, obj.int_impl); std::swap(ext_impl, obj.ext_impl); } //! \brief Returns true if current implementation is internal, otherwise false bool internal() const { assert((int_impl && !ext_impl) || (!int_impl && ext_impl)); return int_impl; } //! \brief Returns true if current implementation is external, otherwise false bool external() const { assert((int_impl && !ext_impl) || (!int_impl && ext_impl)); return ext_impl; } bool empty() const { assert((int_impl && !ext_impl) || (!int_impl && ext_impl)); return (int_impl) ? int_impl->empty() : ext_impl->empty(); } size_type size() const { assert((int_impl && !ext_impl) || (!int_impl && ext_impl)); return (int_impl) ? size_type(int_impl->size()) : ext_impl->size(); } value_type & top() { assert((int_impl && !ext_impl) || (!int_impl && ext_impl)); return (int_impl) ? int_impl->top() : ext_impl->top(); } const value_type & top() const { assert((int_impl && !ext_impl) || (!int_impl && ext_impl)); return (int_impl) ? int_impl->top() : ext_impl->top(); } void push(const value_type & val) { assert((int_impl && !ext_impl) || (!int_impl && ext_impl)); if (int_impl) { int_impl->push(val); if (int_impl->size() == critical_size) { // migrate to external stack ext_impl = new ext_stack_type(*int_impl); delete int_impl; int_impl = NULL; } } else ext_impl->push(val); } void pop() { assert((int_impl && !ext_impl) || (!int_impl && ext_impl)); if (int_impl) int_impl->pop(); else ext_impl->pop(); } virtual ~migrating_stack() { delete int_impl; delete ext_impl; } }; //! \} //! \addtogroup stlcont //! \{ enum stack_externality { external, migrating, internal }; enum stack_behaviour { normal, grow_shrink, grow_shrink2 }; //! \brief Stack type generator //! \tparam ValTp type of contained objects (POD with no references to internal memory) //! \tparam Externality one of //! - \c external , \b external container, implementation is chosen according //! to \c Behaviour parameter, is default //! - \c migrating , migrates from internal implementation given by \c IntStackTp parameter //! to external implementation given by \c Behaviour parameter when size exceeds \c MigrCritSize //! - \c internal , choses \c IntStackTp implementation //! \tparam Behaviour chooses \b external implementation, one of: //! - \c normal , conservative version, implemented in \c stxxl::normal_stack , is default //! - \c grow_shrink , efficient version, implemented in \c stxxl::grow_shrink_stack //! - \c grow_shrink2 , efficient version, implemented in \c stxxl::grow_shrink_stack2 //! \tparam BlocksPerPage defines how many blocks has one page of internal cache of an //! \b external implementation, default is four. All \b external implementations have //! \b two pages. //! \tparam BlkSz external block size in bytes, default is 2 MiB //! \tparam IntStackTp type of internal stack used for some implementations //! \tparam MigrCritSize threshold value for number of elements when //! \c stxxl::migrating_stack migrates to the external memory //! \tparam AllocStr one of allocation strategies: \c striping , \c RC , \c SR , or \c FR //! default is RC //! \tparam SzTp size type, default is \c stxxl::int64 //! //! Configured stack type is available as \c STACK_GENERATOR<>::result.

//! Examples: //! - \c STACK_GENERATOR::result external stack of \c double's , //! - \c STACK_GENERATOR::result internal stack of \c double's , //! - \c STACK_GENERATOR::result external //! grow-shrink stack of \c double's , //! - \c STACK_GENERATOR::result migrating //! grow-shrink stack of \c double's, internal implementation is \c std::stack , //! - \c STACK_GENERATOR::result migrating //! grow-shrink stack of \c double's with 1 block per page and block size 512 KiB //! (total memory occupied = 1 MiB). //! For configured stack method semantics see documentation of the STL \c std::stack. template < class ValTp, stack_externality Externality = external, stack_behaviour Behaviour = normal, unsigned BlocksPerPage = 4, unsigned BlkSz = STXXL_DEFAULT_BLOCK_SIZE(ValTp), class IntStackTp = std::stack, unsigned_type MigrCritSize = (2 * BlocksPerPage * BlkSz), class AllocStr = STXXL_DEFAULT_ALLOC_STRATEGY, class SzTp = stxxl::int64 > class STACK_GENERATOR { typedef stack_config_generator cfg; typedef typename IF, grow_shrink_stack2 >::result GrShrTp; typedef typename IF, GrShrTp>::result ExtStackTp; typedef typename IF, ExtStackTp>::result MigrOrNotStackTp; public: typedef typename IF::result result; }; //! \} __STXXL_END_NAMESPACE namespace std { template void swap(stxxl::normal_stack & a, stxxl::normal_stack & b) { a.swap(b); } template void swap(stxxl::grow_shrink_stack & a, stxxl::grow_shrink_stack & b) { a.swap(b); } template void swap(stxxl::grow_shrink_stack2 & a, stxxl::grow_shrink_stack2 & b) { a.swap(b); } template void swap(stxxl::migrating_stack & a, stxxl::migrating_stack & b) { a.swap(b); } } #endif // !STXXL_STACK_HEADER // vim: et:ts=4:sw=4 stxxl-1.3.1/include/stxxl/bits/io/0000755000175000017500000000000011536252421016670 5ustar andreasandreasstxxl-1.3.1/include/stxxl/bits/io/mmap_file.h0000644000175000017500000000365011535151017020774 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/io/mmap_file.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2002 Roman Dementiev * Copyright (C) 2008 Andreas Beckmann * Copyright (C) 2009 Johannes Singler * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_MMAP_FILE_HEADER #define STXXL_MMAP_FILE_HEADER #ifndef STXXL_HAVE_MMAP_FILE #ifdef STXXL_BOOST_CONFIG #include #endif #ifndef BOOST_MSVC // mmap call does not exist in Windows #define STXXL_HAVE_MMAP_FILE 1 #else #define STXXL_HAVE_MMAP_FILE 0 #endif #endif #if STXXL_HAVE_MMAP_FILE #include #include #include __STXXL_BEGIN_NAMESPACE //! \weakgroup fileimpl File implementations //! \ingroup iolayer //! Implementations of \c stxxl::file and \c stxxl::request //! for various file access methods //! \{ //! \brief Implementation of memory mapped access file class mmap_file : public ufs_file_base, public disk_queued_file { public: //! \brief constructs file object //! \param filename path of file //! \param mode open mode, see \c stxxl::file::open_modes //! \param disk disk(file) identifier inline mmap_file(const std::string & filename, int mode, int queue_id = DEFAULT_QUEUE, int allocator_id = NO_ALLOCATOR) : ufs_file_base(filename, mode), disk_queued_file(queue_id, allocator_id) { } void serve(const request * req) throw (io_error); const char * io_type() const; }; //! \} __STXXL_END_NAMESPACE #endif // #if STXXL_HAVE_MMAP_FILE #endif // !STXXL_MMAP_FILE_HEADER stxxl-1.3.1/include/stxxl/bits/io/request_operations.h0000644000175000017500000001231711535500414022775 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/io/request_operations.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2002 Roman Dementiev * Copyright (C) 2008, 2009 Andreas Beckmann * Copyright (C) 2009 Johannes Singler * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_IO__REQUEST_OPERATIONS_H_ #define STXXL_IO__REQUEST_OPERATIONS_H_ #include #include #include #include __STXXL_BEGIN_NAMESPACE //! \addtogroup iolayer //! \{ //! \brief Collection of functions to track statuses of a number of requests //! \brief Suspends calling thread until \b all given requests are completed //! \param reqs_begin begin of request sequence to wait for //! \param reqs_end end of request sequence to wait for template void wait_all(request_iterator_ reqs_begin, request_iterator_ reqs_end) { for ( ; reqs_begin != reqs_end; ++reqs_begin) (request_ptr(*reqs_begin))->wait(); } //! \brief Suspends calling thread until \b all given requests are completed //! \param req_array array of request_ptr objects //! \param count size of req_array inline void wait_all(request_ptr req_array[], int count) { wait_all(req_array, req_array + count); } //! \brief Cancel requests //! The specified requests are canceled unless already being processed. //! However, cancelation cannot be guaranteed. //! Cancelled requests must still be waited for in order to ensure correct //! operation. //! \param reqs_begin begin of request sequence //! \param reqs_end end of request sequence //! \return number of request canceled template typename std::iterator_traits::difference_type cancel_all(request_iterator_ reqs_begin, request_iterator_ reqs_end) { typename std::iterator_traits::difference_type num_canceled = 0; while (reqs_begin != reqs_end) { if ((request_ptr(*reqs_begin))->cancel()) ++num_canceled; ++reqs_begin; } return num_canceled; } //! \brief Polls requests //! \param reqs_begin begin of request sequence to poll //! \param reqs_end end of request sequence to poll //! \param index contains index of the \b first completed request if any //! \return \c true if any of requests is completed, then index contains valid value, otherwise \c false template request_iterator_ poll_any(request_iterator_ reqs_begin, request_iterator_ reqs_end) { while (reqs_begin != reqs_end) { if ((request_ptr(*reqs_begin))->poll()) return reqs_begin; ++reqs_begin; } return reqs_end; } //! \brief Polls requests //! \param req_array array of request_ptr objects //! \param count size of req_array //! \param index contains index of the \b first completed request if any //! \return \c true if any of requests is completed, then index contains valid value, otherwise \c false inline bool poll_any(request_ptr req_array[], int count, int & index) { request_ptr * res = poll_any(req_array, req_array + count); index = res - req_array; return res != (req_array + count); } //! \brief Suspends calling thread until \b any of requests is completed //! \param reqs_begin begin of request sequence to wait for //! \param reqs_end end of request sequence to wait for //! \return index in req_array pointing to the \b first completed request template request_iterator_ wait_any(request_iterator_ reqs_begin, request_iterator_ reqs_end) { stats::scoped_wait_timer wait_timer(stats::WAIT_OP_ANY); onoff_switch sw; request_iterator_ cur = reqs_begin, result = reqs_end; for ( ; cur != reqs_end; cur++) { if ((request_ptr(*cur))->add_waiter(&sw)) { // request is already done, no waiter was added to the request result = cur; if (cur != reqs_begin) { while (--cur != reqs_begin) (request_ptr(*cur))->delete_waiter(&sw); (request_ptr(*cur))->delete_waiter(&sw); } (request_ptr(*result))->check_errors(); return result; } } sw.wait_for_on(); for (cur = reqs_begin; cur != reqs_end; cur++) { (request_ptr(*cur))->delete_waiter(&sw); if (result == reqs_end && (request_ptr(*cur))->poll()) result = cur; } return result; } //! \brief Suspends calling thread until \b any of requests is completed //! \param req_array array of \c request_ptr objects //! \param count size of req_array //! \return index in req_array pointing to the \b first completed request inline int wait_any(request_ptr req_array[], int count) { return wait_any(req_array, req_array + count) - req_array; } //! \} __STXXL_END_NAMESPACE #endif // !STXXL_IO__REQUEST_OPERATIONS_H_ // vim: et:ts=4:sw=4 stxxl-1.3.1/include/stxxl/bits/io/request_queue.h0000644000175000017500000000223111535543650021741 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/io/request_queue.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2009 Andreas Beckmann * Copyright (C) 2011 Johannes Singler * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_IO_REQUEST_QUEUE_HEADER #define STXXL_IO_REQUEST_QUEUE_HEADER #include #include __STXXL_BEGIN_NAMESPACE //! \addtogroup iolayer //! \{ class request_queue : private noncopyable { public: enum priority_op { READ, WRITE, NONE }; public: virtual void add_request(request_ptr & req) = 0; virtual bool cancel_request(request_ptr & req) = 0; virtual ~request_queue() { } virtual void set_priority_op(priority_op p) { STXXL_UNUSED(p); } }; //! \} __STXXL_END_NAMESPACE #endif // !STXXL_IO_REQUEST_QUEUE_HEADER // vim: et:ts=4:sw=4 stxxl-1.3.1/include/stxxl/bits/io/boostfd_file.h0000644000175000017500000000354411535151017021504 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/io/boostfd_file.h * * File implementation based on boost::iostreams::file_decriptor * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2006 Roman Dementiev * Copyright (C) 2008 Andreas Beckmann * Copyright (C) 2009 Johannes Singler * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_BOOSTFD_FILE_H_ #define STXXL_BOOSTFD_FILE_H_ #ifndef STXXL_HAVE_BOOSTFD_FILE #ifdef STXXL_BOOST_CONFIG // if boost is available #define STXXL_HAVE_BOOSTFD_FILE 1 #else #define STXXL_HAVE_BOOSTFD_FILE 0 #endif #endif #if STXXL_HAVE_BOOSTFD_FILE #include #include #include __STXXL_BEGIN_NAMESPACE //! \addtogroup fileimpl //! \{ //! \brief Implementation based on boost::iostreams::file_decriptor class boostfd_file : public disk_queued_file { typedef boost::iostreams::file_descriptor fd_type; protected: mutex fd_mutex; // sequentialize function calls involving file_des fd_type file_des; int mode_; offset_type _size(); public: boostfd_file(const std::string & filename, int mode, int queue_id = DEFAULT_QUEUE, int allocator_id = NO_ALLOCATOR); ~boostfd_file(); offset_type size(); void set_size(offset_type newsize); void lock(); void serve(const request * req) throw (io_error); const char * io_type() const; }; //! \} __STXXL_END_NAMESPACE #endif // #if STXXL_HAVE_BOOSTFD_FILE #endif // !STXXL_BOOSTFD_FILE_H_ stxxl-1.3.1/include/stxxl/bits/io/fileperblock_file.h0000644000175000017500000000471211535151017022503 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/io/fileperblock_file.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2008, 2009 Johannes Singler * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_FILEPERBLOCK_FILE_HEADER #define STXXL_FILEPERBLOCK_FILE_HEADER #include #include __STXXL_BEGIN_NAMESPACE //! \addtogroup fileimpl //! \{ //! \brief Implementation of file based on other files, dynamically allocate one file per block. //! Allows for dynamic disk space consumption. template class fileperblock_file : public disk_queued_file { private: std::string filename_prefix; int mode; unsigned_type current_size; bool lock_file_created; base_file_type lock_file; protected: //! \brief Constructs a file name for a given block. std::string filename_for_block(unsigned_type offset); public: //! \brief constructs file object //! \param filename_prefix filename prefix, numbering will be appended to it //! \param mode open mode, see \c file::open_modes //! \param disk disk(file) identifier fileperblock_file( const std::string & filename_prefix, int mode, int queue_id = DEFAULT_QUEUE, int allocator_id = NO_ALLOCATOR); virtual ~fileperblock_file(); virtual void serve(const request * req) throw (io_error); //! \brief Changes the size of the file //! \param new_size value of the new file size virtual void set_size(offset_type new_size) { current_size = new_size; } //! \brief Returns size of the file //! \return file size in length virtual offset_type size() { return current_size; } virtual void lock(); //! \brief Frees the specified region. //! Actually deletes the corresponding file if the whole thing is deleted. virtual void discard(offset_type offset, offset_type length); //! Rename the file corresponding to the offset such that it is out of reach for deleting. virtual void export_files(offset_type offset, offset_type length, std::string filename); const char * io_type() const; }; //! \} __STXXL_END_NAMESPACE #endif // !STXXL_FILEPERBLOCK_FILE_HEADER stxxl-1.3.1/include/stxxl/bits/io/disk_queued_file.h0000644000175000017500000000300611535554225022347 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/io/disk_queued_file.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2008 Andreas Beckmann * Copyright (C) 2009 Johannes Singler * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_HEADER_IO_DISK_QUEUED_FILE #define STXXL_HEADER_IO_DISK_QUEUED_FILE #include __STXXL_BEGIN_NAMESPACE //! \addtogroup fileimpl //! \{ //! \brief Implementation of some file methods based on serving_request class disk_queued_file : public virtual file { int queue_id, allocator_id; public: disk_queued_file(int queue_id, int allocator_id) : queue_id(queue_id), allocator_id(allocator_id) { } request_ptr aread( void * buffer, offset_type pos, size_type bytes, const completion_handler & on_cmpl); request_ptr awrite( void * buffer, offset_type pos, size_type bytes, const completion_handler & on_cmpl); virtual int get_queue_id() const { return queue_id; } virtual int get_allocator_id() const { return allocator_id; } }; //! \} __STXXL_END_NAMESPACE #endif // !STXXL_HEADER_IO_DISK_QUEUED_FILE // vim: et:ts=4:sw=4 stxxl-1.3.1/include/stxxl/bits/io/simdisk_file.h0000644000175000017500000000776711535151017021522 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/io/simdisk_file.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2002-2003 Roman Dementiev * Copyright (C) 2008 Andreas Beckmann * Copyright (C) 2009 Johannes Singler * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_SIMDISK_FILE_HEADER #define STXXL_SIMDISK_FILE_HEADER #ifndef STXXL_HAVE_SIMDISK_FILE #ifdef STXXL_BOOST_CONFIG #include #endif #ifndef BOOST_MSVC // mmap call does not exist in Windows #define STXXL_HAVE_SIMDISK_FILE 1 #else #define STXXL_HAVE_SIMDISK_FILE 0 #endif #endif #if STXXL_HAVE_SIMDISK_FILE #include #include #include #include #include __STXXL_BEGIN_NAMESPACE //! \addtogroup fileimpl //! \{ #define AVERAGE_SPEED (15 * 1024 * 1024) class DiskGeometry : private noncopyable { struct Zone { // manufactured data #if 0 int last_cyl; int sect_per_track; #endif // derived data int first_sector; int sectors; double sustained_data_rate; // in MiB/s inline Zone(int _first_sector) : first_sector(_first_sector) { } // constructor for zone search inline Zone( #if 0 int _last_cyl, int _sect_per_track, #endif int _first_sector, int _sectors, double _rate) : #if 0 last_cyl(_last_cyl), sect_per_track(_sect_per_track), #endif first_sector(_first_sector), sectors(_sectors), sustained_data_rate(_rate) { } }; struct ZoneCmp { inline bool operator () (const Zone & a, const Zone & b) const { return a.first_sector < b.first_sector; } }; protected: int nsurfaces; int bytes_per_sector; double cmd_ovh; // in s double seek_time; // in s double rot_latency; // in s double head_switch_time; // in s double cyl_switch_time; // in s double revolution_time; // in s double interface_speed; // in byte/s std::set zones; void add_zone(int & first_cyl, int last_cyl, int sec_per_track, int & first_sect); public: inline DiskGeometry() { } double get_delay(file::offset_type offset, file::size_type size); // returns delay in s inline ~DiskGeometry() { } }; class IC35L080AVVA07 : public DiskGeometry // IBM series 120GXP { public: IC35L080AVVA07(); }; //! \brief Implementation of disk emulation //! \remark It is emulation of IBM IC35L080AVVA07 disk's timings class sim_disk_file : public ufs_file_base, public disk_queued_file, public IC35L080AVVA07 { public: //! \brief constructs file object //! \param filename path of file //! \attention filename must be resided at memory disk partition //! \param mode open mode, see \c stxxl::file::open_modes //! \param disk disk(file) identifier inline sim_disk_file(const std::string & filename, int mode, int queue_id = DEFAULT_QUEUE, int allocator_id = NO_ALLOCATOR) : ufs_file_base(filename, mode), disk_queued_file(queue_id, allocator_id) { std::cout << "Please, make sure that '" << filename << "' is resided on swap memory partition!" << std::endl; } void serve(const request * req) throw (io_error); void set_size(offset_type newsize); const char * io_type() const; }; //! \} __STXXL_END_NAMESPACE #endif // #if STXXL_HAVE_SIMDISK_FILE #endif // !STXXL_SIMDISK_FILE_HEADER stxxl-1.3.1/include/stxxl/bits/io/create_file.h0000644000175000017500000000166711463025076021320 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/io/create_file.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2010 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_IO__CREATE_FILE_H_ #define STXXL_IO__CREATE_FILE_H_ #include __STXXL_BEGIN_NAMESPACE file * create_file(const std::string & io_impl, const std::string & filename, int options, int physical_device_id = file::DEFAULT_QUEUE, int allocator_id = file::NO_ALLOCATOR); __STXXL_END_NAMESPACE #endif // !STXXL_IO__CREATE_FILE_H_ // vim: et:ts=4:sw=4 stxxl-1.3.1/include/stxxl/bits/io/iobase.h0000644000175000017500000000172411111325125020276 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/io/iobase.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2002 Roman Dementiev * Copyright (C) 2008 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_IOBASE_HEADER #define STXXL_IOBASE_HEADER #include #warning this is an obsolete header __STXXL_BEGIN_NAMESPACE //! \defgroup iolayer I/O primitives layer //! Group of classes which enable abstraction from operating system calls and support //! system-independent interfaces for asynchronous I/O. //! \{ //! \} __STXXL_END_NAMESPACE #endif // !STXXL_IOBASE_HEADER // vim: et:ts=4:sw=4 stxxl-1.3.1/include/stxxl/bits/io/request_queue_impl_worker.h0000644000175000017500000000322311535151017024345 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/io/request_queue_impl_worker.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2002 Roman Dementiev * Copyright (C) 2008, 2009 Andreas Beckmann * Copyright (C) 2009 Johannes Singler * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_IO_REQUEST_QUEUE_IMPL_WORKER_HEADER #define STXXL_IO_REQUEST_QUEUE_IMPL_WORKER_HEADER #ifdef STXXL_BOOST_CONFIG #include #endif #ifdef STXXL_BOOST_THREADS // Use Portable Boost threads #include #else #include #endif #include #include #include __STXXL_BEGIN_NAMESPACE //! \addtogroup iolayer //! \{ class request_queue_impl_worker : public request_queue { protected: enum thread_state { NOT_RUNNING, RUNNING, TERMINATING, TERMINATE = TERMINATING }; #ifdef STXXL_BOOST_THREADS typedef boost::thread * thread_type; #else typedef pthread_t thread_type; #endif protected: void start_thread(void * (*worker)(void *), void * arg, thread_type & t, state & s); void stop_thread(thread_type & t, state & s, semaphore & sem); }; //! \} __STXXL_END_NAMESPACE #endif // !STXXL_IO_REQUEST_QUEUE_IMPL_WORKER_HEADER // vim: et:ts=4:sw=4 stxxl-1.3.1/include/stxxl/bits/io/completion_handler.h0000644000175000017500000000535211504156375022722 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/io/completion_handler.h * * Loki-style completion handler (functors) * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2003 Roman Dementiev * Copyright (C) 2008 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_COMPLETION_HANDLER_HEADER #define STXXL_COMPLETION_HANDLER_HEADER #include #include __STXXL_BEGIN_NAMESPACE class request; class completion_handler_impl { public: virtual void operator () (request *) = 0; virtual completion_handler_impl * clone() const = 0; virtual ~completion_handler_impl() { } }; template class completion_handler1 : public completion_handler_impl { private: handler_type handler_; public: completion_handler1(const handler_type & handler__) : handler_(handler__) { } completion_handler1 * clone() const { return new completion_handler1(*this); } void operator () (request * req) { handler_(req); } }; //! \brief Completion handler class (Loki-style) //! In some situations one needs to execute //! some actions after completion of an I/O //! request. In these cases one can use //! an I/O completion handler - a function //! object that can be passed as a parameter //! to asynchronous I/O calls \c stxxl::file::aread //! and \c stxxl::file::awrite . //! For an example of use see \link mng/test_mng.cpp mng/test_mng.cpp \endlink class completion_handler { compat_unique_ptr::result sp_impl_; public: completion_handler() : sp_impl_(static_cast(0)) { } completion_handler(const completion_handler & obj) : sp_impl_(obj.sp_impl_.get()->clone()) { } template completion_handler(const handler_type & handler__) : sp_impl_(new completion_handler1(handler__)) { } completion_handler & operator = (const completion_handler & obj) { sp_impl_.reset(obj.sp_impl_.get()->clone()); return *this; } void operator () (request * req) { (*sp_impl_)(req); } }; //! \brief Default completion handler class struct default_completion_handler { //! \brief An operator that does nothing void operator () (request *) { } }; __STXXL_END_NAMESPACE #endif // !STXXL_COMPLETION_HANDLER_HEADER // vim: et:ts=4:sw=4 stxxl-1.3.1/include/stxxl/bits/io/wbtl_file.h0000644000175000017500000000654211535151017021015 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/io/wbtl_file.h * * a write-buffered-translation-layer pseudo file * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2008-2009 Andreas Beckmann * Copyright (C) 2009 Johannes Singler * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_WBTL_FILE_HEADER #define STXXL_WBTL_FILE_HEADER #ifndef STXXL_HAVE_WBTL_FILE #define STXXL_HAVE_WBTL_FILE 1 #endif #if STXXL_HAVE_WBTL_FILE #include #include __STXXL_BEGIN_NAMESPACE //! \addtogroup fileimpl //! \{ //! \brief Implementation of file based on buffered writes and //! block remapping via a translation layer. class wbtl_file : public disk_queued_file { typedef std::pair place; typedef std::map sortseq; typedef std::map place_map; // the physical disk used as backend file * storage; offset_type sz; size_type write_block_size; mutex mapping_mutex; // logical to physical address translation sortseq address_mapping; // physical to (logical address, size) translation place_map reverse_mapping; // list of free (physical) regions sortseq free_space; offset_type free_bytes; // the write buffers: // write_buffer[curbuf] is the current write buffer // write_buffer[1-curbuf] is the previous write buffer // buffer_address if the start offset on the backend file // curpos is the next writing position in write_buffer[curbuf] mutex buffer_mutex; char * write_buffer[2]; offset_type buffer_address[2]; int curbuf; size_type curpos; request_ptr backend_request; struct FirstFit : public std::binary_function { bool operator () ( const place & entry, const offset_type size) const { return (entry.second >= size); } }; public: //! \brief constructs file object //! \param backend_file file object used as storage backend, will be deleted in ~wbtl_file() //! \param disk disk(file) identifier wbtl_file( file * backend_file, size_type write_buffer_size, int write_buffers = 2, int queue_id = DEFAULT_QUEUE, int allocator_id = NO_ALLOCATOR); ~wbtl_file(); offset_type size(); void set_size(offset_type newsize); void lock(); void serve(const request * req) throw (io_error); void discard(offset_type offset, offset_type size); const char * io_type() const; private: void _add_free_region(offset_type offset, offset_type size); protected: void sread(void * buffer, offset_type offset, size_type bytes); void swrite(void * buffer, offset_type offset, size_type bytes); offset_type get_next_write_block(); void check_corruption(offset_type region_pos, offset_type region_size, sortseq::iterator pred, sortseq::iterator succ); }; //! \} __STXXL_END_NAMESPACE #endif // #if STXXL_HAVE_WBTL_FILE #endif // !STXXL_WBTL_FILE_HEADER stxxl-1.3.1/include/stxxl/bits/io/io.h0000644000175000017500000000215011535500414017443 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/io/io.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2002 Roman Dementiev * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_IO_HEADER #define STXXL_IO_HEADER #include #include #include #include #include #include #include #include #include #include #include #include #include //! \brief \c \ library namespace __STXXL_BEGIN_NAMESPACE __STXXL_END_NAMESPACE #endif // !STXXL_IO_HEADER stxxl-1.3.1/include/stxxl/bits/io/request_interface.h0000644000175000017500000000530111535637727022567 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/io/request_interface.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2002 Roman Dementiev * Copyright (C) 2008, 2009, 2011 Andreas Beckmann * Copyright (C) 2009 Johannes Singler * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_IO__REQUEST_INTERFACE_H_ #define STXXL_IO__REQUEST_INTERFACE_H_ #include #include #include #include __STXXL_BEGIN_NAMESPACE //! \addtogroup iolayer //! \{ class onoff_switch; //! \brief Functional interface of a request //! Since all library I/O operations are asynchronous, //! one needs to keep track of their status: //! e.g. whether an I/O operation completed or not. class request_interface : private noncopyable { public: typedef stxxl::external_size_type offset_type; typedef stxxl::internal_size_type size_type; enum request_type { READ, WRITE }; public: virtual bool add_waiter(onoff_switch * sw) = 0; virtual void delete_waiter(onoff_switch * sw) = 0; protected: virtual void notify_waiters() = 0; public: // HACK! virtual void serve() = 0; protected: virtual void completed() = 0; public: //! \brief Suspends calling thread until completion of the request virtual void wait(bool measure_time = true) = 0; //! \brief Cancel a request. //! //! The request is canceled unless already being processed. //! However, cancelation cannot be guaranteed. //! Canceled requests must still be waited for in order to ensure correct operation. //! If the request was canceled successfully, the completion handler will not be called. //! \return \c true iff the request was canceled successfully virtual bool cancel() = 0; //! \brief Polls the status of the request //! \return \c true if request is completed, otherwise \c false virtual bool poll() = 0; //! \brief Identifies the type of I/O implementation //! \return pointer to null terminated string of characters, containing the name of I/O implementation virtual const char * io_type() const = 0; //! \brief Dumps properties of a request virtual std::ostream & print(std::ostream & out) const = 0; virtual ~request_interface() { } }; //! \} __STXXL_END_NAMESPACE #endif // !STXXL_IO__REQUEST_INTERFACE_H_ // vim: et:ts=4:sw=4 stxxl-1.3.1/include/stxxl/bits/io/syscall_file.h0000644000175000017500000000311011535151017021503 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/io/syscall_file.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2002 Roman Dementiev * Copyright (C) 2008 Andreas Beckmann * Copyright (C) 2009 Johannes Singler * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_SYSCALL_FILE_HEADER #define STXXL_SYSCALL_FILE_HEADER #include #include __STXXL_BEGIN_NAMESPACE //! \addtogroup fileimpl //! \{ //! \brief Implementation of file based on UNIX syscalls class syscall_file : public ufs_file_base, public disk_queued_file { public: //! \brief constructs file object //! \param filename path of file //! \attention filename must be resided at memory disk partition //! \param mode open mode, see \c stxxl::file::open_modes //! \param disk disk(file) identifier syscall_file( const std::string & filename, int mode, int queue_id = DEFAULT_QUEUE, int allocator_id = NO_ALLOCATOR) : ufs_file_base(filename, mode), disk_queued_file(queue_id, allocator_id) { } void serve(const request * req) throw (io_error); const char * io_type() const; }; //! \} __STXXL_END_NAMESPACE #endif // !STXXL_SYSCALL_FILE_HEADER stxxl-1.3.1/include/stxxl/bits/io/request_ptr.h0000644000175000017500000000746011535536713021435 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/io/request_ptr.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2002 Roman Dementiev * Copyright (C) 2009 Johannes Singler * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_IO__REQUEST_PTR_H_ #define STXXL_IO__REQUEST_PTR_H_ #include #include #include #include __STXXL_BEGIN_NAMESPACE //! \addtogroup iolayer //! \{ //! \brief A smart wrapper for \c request pointer. #define STXXL_VERBOSE_request_ptr(msg) STXXL_VERBOSE3("[" << static_cast(this) << "] request_ptr::" << msg << " ptr=" << static_cast(ptr)) //! Implemented as reference counting smart pointer. class request_ptr { request * ptr; void add_ref() { if (ptr) { ptr->add_ref(); } } void sub_ref() { if (ptr) { if (ptr->sub_ref()) { STXXL_VERBOSE_request_ptr("sub_ref(): the last ref, deleting"); delete ptr; ptr = NULL; } else { STXXL_VERBOSE_request_ptr("sub_ref(): more refs left"); } } } public: //! \brief Constructs an \c request_ptr from \c request pointer request_ptr(request * ptr_ = NULL) : ptr(ptr_) { STXXL_VERBOSE_request_ptr("(request*)"); add_ref(); } //! \brief Constructs an \c request_ptr from a \c request_ptr object request_ptr(const request_ptr & p) : ptr(p.ptr) { STXXL_VERBOSE_request_ptr("(request_ptr&)"); add_ref(); } //! \brief Destructor ~request_ptr() { STXXL_VERBOSE_request_ptr("~()"); sub_ref(); } //! \brief Assignment operator from \c request_ptr object //! \return reference to itself request_ptr & operator = (const request_ptr & p) { // assert(p.ptr); return (*this = p.ptr); //call the operator below; } //! \brief Assignment operator from \c request pointer //! \return reference to itself request_ptr & operator = (request * p) { STXXL_VERBOSE_request_ptr("operator=(request=" << static_cast(p) << ") {BEGIN}"); if (p != ptr) { sub_ref(); ptr = p; add_ref(); } STXXL_VERBOSE_request_ptr("operator=(request=" << static_cast(p) << ") {END}"); return *this; } //! \brief "Star" operator //! \return reference to owned \c request object request & operator * () const { assert(ptr); return *ptr; } //! \brief "Arrow" operator //! \return pointer to owned \c request object request * operator -> () const { assert(ptr); return ptr; } bool operator == (const request_ptr & rp2) const { return ptr == rp2.ptr; } //! \brief Access to owned \c request object (synonym for \c operator->() ) //! \return reference to owned \c request object //! \warning Creation another \c request_ptr from the returned \c request or deletion //! causes unpredictable behaviour. Do not do that! request * get() const { return ptr; } //! \brief Returns true if object is initialized bool valid() const { return ptr != NULL; } //! \brief Returns true if object is not initialized bool empty() const { return ptr == NULL; } }; //! \} __STXXL_END_NAMESPACE #endif // !STXXL_IO__REQUEST_PTR_H_ // vim: et:ts=4:sw=4 stxxl-1.3.1/include/stxxl/bits/io/mem_file.h0000644000175000017500000000264011535151017020616 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/io/mem_file.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2008 Andreas Beckmann * Copyright (C) 2009 Johannes Singler * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_MEM_FILE_HEADER #define STXXL_MEM_FILE_HEADER #include #include __STXXL_BEGIN_NAMESPACE //! \addtogroup fileimpl //! \{ //! \brief Implementation of file based on new[] and memcpy class mem_file : public disk_queued_file { char * ptr; offset_type sz; public: //! \brief constructs file object //! \param disk disk(file) identifier mem_file( int queue_id = DEFAULT_QUEUE, int allocator_id = NO_ALLOCATOR) : disk_queued_file(queue_id, allocator_id), ptr(NULL), sz(0) { } void serve(const request * req) throw (io_error); ~mem_file(); offset_type size(); void set_size(offset_type newsize); void lock(); void discard(offset_type offset, offset_type size); const char * io_type() const; }; //! \} __STXXL_END_NAMESPACE #endif // !STXXL_MEM_FILE_HEADER stxxl-1.3.1/include/stxxl/bits/io/request_queue_impl_1q.h0000644000175000017500000000365711535543650023400 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/io/request_queue_impl_1q.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2002 Roman Dementiev * Copyright (C) 2008-2009 Andreas Beckmann * Copyright (C) 2009 Johannes Singler * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_IO_REQUEST_QUEUE_IMPL_1Q_HEADER #define STXXL_IO_REQUEST_QUEUE_IMPL_1Q_HEADER #include #include #include __STXXL_BEGIN_NAMESPACE //! \addtogroup iolayer //! \{ class request_queue_impl_1q : public request_queue_impl_worker { private: typedef request_queue_impl_1q self; typedef std::list queue_type; mutex queue_mutex; queue_type queue; state _thread_state; thread_type thread; semaphore sem; static const priority_op _priority_op = WRITE; static void * worker(void * arg); public: // \param n max number of requests simultaneously submitted to disk request_queue_impl_1q(int n = 1); // in a multi-threaded setup this does not work as intended // also there were race conditions possible // and actually an old value was never restored once a new one was set ... // so just disable it and all it's nice implications void set_priority_op(priority_op op) { //_priority_op = op; STXXL_UNUSED(op); } void add_request(request_ptr & req); bool cancel_request(request_ptr & req); ~request_queue_impl_1q(); }; //! \} __STXXL_END_NAMESPACE #endif // !STXXL_IO_REQUEST_QUEUE_IMPL_1Q_HEADER // vim: et:ts=4:sw=4 stxxl-1.3.1/include/stxxl/bits/io/file.h0000644000175000017500000001562211535500414017763 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/io/file.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2002 Roman Dementiev * Copyright (C) 2008, 2010 Andreas Beckmann * Copyright (C) 2008, 2009 Johannes Singler * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_IO_FILE_HEADER #define STXXL_IO_FILE_HEADER #ifdef STXXL_BOOST_CONFIG #include #endif #if defined (__linux__) #define STXXL_CHECK_BLOCK_ALIGNING #endif #include #include #include #ifdef BOOST_MSVC // this is not stxxl/bits/io/io.h ! #include #else #include #include #include #endif //#ifdef __sun__ //#define O_DIRECT 0 //#endif #ifndef O_SYNC #define O_SYNC 0 #endif #ifndef O_RSYNC #define O_RSYNC 0 #endif #ifndef O_DSYNC #define O_DSYNC 0 #endif #if defined (__linux__) #if ! defined(O_DIRECT) #error O_DIRECT is not defined while __linux__ is - PLEASE REPORT THIS BUG #endif //#include // FIXME: In which conditions is this not defined? Why only i386 and alpha? Why not amd64? #if !defined (O_DIRECT) && (defined (__alpha__) || defined (__i386__)) #define O_DIRECT 040000 /* direct disk access */ #endif #endif #ifndef O_DIRECT #define O_DIRECT O_SYNC #endif #include #include #include #include #include #include #include #include __STXXL_BEGIN_NAMESPACE //! \addtogroup iolayer //! \{ //! \brief Defines interface of file //! It is a base class for different implementations that might //! base on various file systems or even remote storage interfaces class file : private noncopyable { mutex request_ref_cnt_mutex; int request_ref_cnt; protected: //! \brief Initializes file object //! \param _id file identifier //! \remark Called in implementations of file file() : request_ref_cnt(0) { } public: // the offset of a request, also the size of the file typedef request::offset_type offset_type; // the size of a request typedef request::size_type size_type; //! \brief Definition of acceptable file open modes //! Various open modes in a file system must be //! converted to this set of acceptable modes enum open_mode { RDONLY = 1, //!< only reading of the file is allowed WRONLY = 2, //!< only writing of the file is allowed RDWR = 4, //!< read and write of the file are allowed CREAT = 8, //!< in case file does not exist no error occurs and file is newly created DIRECT = 16, //!< I/Os proceed bypassing file system buffers, i.e. unbuffered I/O TRUNC = 32, //!< once file is opened its length becomes zero SYNC = 64, //!< open the file with O_SYNC | O_DSYNC | O_RSYNC flags set NO_LOCK = 128, //!< do not aquire an exclusive lock by default }; static const int DEFAULT_QUEUE = -1; static const int NO_QUEUE = -2; static const int NO_ALLOCATOR = -1; //! \brief Schedules an asynchronous read request to the file //! \param buffer pointer to memory buffer to read into //! \param pos file position to start read from //! \param bytes number of bytes to transfer //! \param on_cmpl I/O completion handler //! \return \c request_ptr request object, which can be used to track the status of the operation virtual request_ptr aread(void * buffer, offset_type pos, size_type bytes, const completion_handler & on_cmpl) = 0; //! \brief Schedules an asynchronous write request to the file //! \param buffer pointer to memory buffer to write from //! \param pos starting file position to write //! \param bytes number of bytes to transfer //! \param on_cmpl I/O completion handler //! \return \c request_ptr request object, which can be used to track the status of the operation virtual request_ptr awrite(void * buffer, offset_type pos, size_type bytes, const completion_handler & on_cmpl) = 0; virtual void serve(const request * req) throw (io_error) = 0; void add_request_ref() { scoped_mutex_lock Lock(request_ref_cnt_mutex); ++request_ref_cnt; } void delete_request_ref() { scoped_mutex_lock Lock(request_ref_cnt_mutex); assert(request_ref_cnt > 0); --request_ref_cnt; } int get_request_nref() { scoped_mutex_lock Lock(request_ref_cnt_mutex); return request_ref_cnt; } //! \brief Changes the size of the file //! \param newsize new file size virtual void set_size(offset_type newsize) = 0; //! \brief Returns size of the file //! \return file size in bytes virtual offset_type size() = 0; //! \brief Returns the identifier of the file's queue //! \remark Files allocated on the same physical device usually share the same queue //! \return queue number virtual int get_queue_id() const = 0; //! \brief Returns the file's allocator //! \return allocator number virtual int get_allocator_id() const = 0; virtual int get_physical_device_id() const { return get_queue_id(); } //! \brief Locks file for reading and writing (acquires a lock in the file system) virtual void lock() = 0; //! \brief Discard a region of the file (mark it unused) //! some specialized file types may need to know freed regions virtual void discard(offset_type offset, offset_type size) { STXXL_UNUSED(offset); STXXL_UNUSED(size); } virtual void export_files(offset_type offset, offset_type length, std::string prefix) { STXXL_UNUSED(offset); STXXL_UNUSED(length); STXXL_UNUSED(prefix); } virtual void remove() { } virtual ~file() { int nr = get_request_nref(); if (nr != 0) STXXL_ERRMSG("stxxl::file is being deleted while there are still " << nr << " (unfinished) requests referencing it"); } //! \brief Identifies the type of I/O implementation //! \return pointer to null terminated string of characters, containing the name of I/O implementation virtual const char * io_type() const { return "none"; } }; //! \} __STXXL_END_NAMESPACE #endif // !STXXL_IO_FILE_HEADER // vim: et:ts=4:sw=4 stxxl-1.3.1/include/stxxl/bits/io/disk_queues.h0000644000175000017500000000636411535543650021401 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/io/disk_queues.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2002 Roman Dementiev * Copyright (C) 2008-2010 Andreas Beckmann * Copyright (C) 2009 Johannes Singler * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_IO_DISK_QUEUES_HEADER #define STXXL_IO_DISK_QUEUES_HEADER #include #include #include #include #include __STXXL_BEGIN_NAMESPACE //! \addtogroup iolayer //! \{ class request_ptr; //! \brief Encapsulates disk queues //! \remark is a singleton class disk_queues : public singleton { friend class singleton; // 2 queues: write queue and read queue typedef request_queue_impl_qwqr request_queue_type; typedef stxxl::int64 DISKID; typedef std::map request_queue_map; protected: request_queue_map queues; disk_queues() { stxxl::stats::get_instance(); // initialize stats before ourselves } public: void add_request(request_ptr & req, DISKID disk) { #ifdef STXXL_HACK_SINGLE_IO_THREAD disk = 42; #endif if (queues.find(disk) == queues.end()) { // create new request queue queues[disk] = new request_queue_type(); } queues[disk]->add_request(req); } //! \brief Cancel a request //! The specified request is canceled unless already being processed. //! However, cancelation cannot be guaranteed. //! Cancelled requests must still be waited for in order to ensure correct //! operation. //! \param req request to cancel //! \param disk disk number for disk that \c req was scheduled on //! \return \c true iff the request was canceled successfully bool cancel_request(request_ptr & req, DISKID disk) { #ifdef STXXL_HACK_SINGLE_IO_THREAD disk = 42; #endif if (queues.find(disk) != queues.end()) return queues[disk]->cancel_request(req); else return false; } ~disk_queues() { // deallocate all queues for (request_queue_map::iterator i = queues.begin(); i != queues.end(); i++) delete (*i).second; } //! \brief Changes requests priorities //! \param op one of: //! - READ, read requests are served before write requests within a disk queue //! - WRITE, write requests are served before read requests within a disk queue //! - NONE, read and write requests are served by turns, alternately void set_priority_op(request_queue::priority_op op) { for (request_queue_map::iterator i = queues.begin(); i != queues.end(); i++) i->second->set_priority_op(op); } }; //! \} __STXXL_END_NAMESPACE #endif // !STXXL_IO_DISK_QUEUES_HEADER // vim: et:ts=4:sw=4 stxxl-1.3.1/include/stxxl/bits/io/request_with_waiters.h0000644000175000017500000000247611535655623023345 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/io/request_with_waiters.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2002 Roman Dementiev * Copyright (C) 2008 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_IO__REQUEST_WITH_WAITERS_H_ #define STXXL_IO__REQUEST_WITH_WAITERS_H_ #include #include #include #include __STXXL_BEGIN_NAMESPACE //! \addtogroup fileimpl //! \{ //! \brief Request that is aware of threads waiting for it to complete. class request_with_waiters : virtual public request_interface { mutex waiters_mutex; std::set waiters; protected: bool add_waiter(onoff_switch * sw); void delete_waiter(onoff_switch * sw); void notify_waiters(); /* int nwaiters(); // returns number of waiters */ }; //! \} __STXXL_END_NAMESPACE #endif // !STXXL_IO__REQUEST_WITH_WAITERS_H_ // vim: et:ts=4:sw=4 stxxl-1.3.1/include/stxxl/bits/io/request_with_state.h0000644000175000017500000000312711535637727023006 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/io/request_with_state.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2008 Andreas Beckmann * Copyright (C) 2009 Johannes Singler * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_IO__REQUEST_WITH_STATE_H_ #define STXXL_IO__REQUEST_WITH_STATE_H_ #include #include #include __STXXL_BEGIN_NAMESPACE //! \addtogroup fileimpl //! \{ //! \brief Request with completion state. class request_with_state : public request, public request_with_waiters { protected: //! states of request //! OP - operating, DONE - request served, READY2DIE - can be destroyed enum request_state { OP = 0, DONE = 1, READY2DIE = 2 }; state _state; protected: request_with_state( const completion_handler & on_cmpl, file * f, void * buf, offset_type off, size_type b, request_type t) : request(on_cmpl, f, buf, off, b, t), _state(OP) { } public: virtual ~request_with_state(); void wait(bool measure_time = true); bool poll(); bool cancel(); }; //! \} __STXXL_END_NAMESPACE #endif // !STXXL_IO__REQUEST_WITH_STATE_H_ // vim: et:ts=4:sw=4 stxxl-1.3.1/include/stxxl/bits/io/serving_request.h0000644000175000017500000000245411535655623022305 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/io/serving_request.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2002 Roman Dementiev * Copyright (C) 2008 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_IO__SERVING_REQUEST_H_ #define STXXL_IO__SERVING_REQUEST_H_ #include __STXXL_BEGIN_NAMESPACE //! \addtogroup iolayer //! \{ //! \brief Request which serves an I/O by calling the synchronous routine of the file. class serving_request : public request_with_state { template friend class fileperblock_file; public: serving_request( const completion_handler & on_cmpl, file * f, void * buf, offset_type off, size_type b, request_type t); protected: void serve(); void completed(); public: const char * io_type() const; }; //! \} __STXXL_END_NAMESPACE #endif // !STXXL_IO__SERVING_REQUEST_H_ // vim: et:ts=4:sw=4 stxxl-1.3.1/include/stxxl/bits/io/iostats.h0000644000175000017500000004003111535151017020523 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/io/iostats.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2002-2004 Roman Dementiev * Copyright (C) 2008-2010 Andreas Beckmann * Copyright (C) 2009, 2010 Johannes Singler * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_IOSTATS_HEADER #define STXXL_IOSTATS_HEADER #ifndef STXXL_IO_STATS #define STXXL_IO_STATS 1 #endif #include #include #include #include #include #include #include #include #include __STXXL_BEGIN_NAMESPACE //! \addtogroup iolayer //! //! \{ //! \brief Collects various I/O statistics //! \remarks is a singleton class stats : public singleton { friend class singleton; unsigned reads, writes; // number of operations int64 volume_read, volume_written; // number of bytes read/written unsigned c_reads, c_writes; // number of cached operations int64 c_volume_read, c_volume_written; // number of bytes read/written from/to cache double t_reads, t_writes; // seconds spent in operations double p_reads, p_writes; // seconds spent in parallel operations double p_begin_read, p_begin_write; // start time of parallel operation double p_ios; // seconds spent in all parallel I/O operations (read and write) double p_begin_io; double t_waits, p_waits; // seconds spent waiting for completion of I/O operations double p_begin_wait; double t_wait_read, p_wait_read; double p_begin_wait_read; double t_wait_write, p_wait_write; double p_begin_wait_write; int acc_reads, acc_writes; // number of requests, participating in parallel operation int acc_ios; int acc_waits; int acc_wait_read, acc_wait_write; double last_reset; mutex read_mutex, write_mutex, io_mutex, wait_mutex; stats(); public: enum wait_op_type { WAIT_OP_ANY, WAIT_OP_READ, WAIT_OP_WRITE }; class scoped_read_write_timer { typedef unsigned_type size_type; bool is_write; #if STXXL_IO_STATS bool running; #endif public: scoped_read_write_timer(size_type size, bool is_write = false) : is_write(is_write) #if STXXL_IO_STATS , running(false) #endif { start(size); } ~scoped_read_write_timer() { stop(); } void start(size_type size) { #if STXXL_IO_STATS if (!running) { running = true; if (is_write) stats::get_instance()->write_started(size); else stats::get_instance()->read_started(size); } #else STXXL_UNUSED(size); #endif } void stop() { #if STXXL_IO_STATS if (running) { if (is_write) stats::get_instance()->write_finished(); else stats::get_instance()->read_finished(); running = false; } #endif } }; class scoped_write_timer { typedef unsigned_type size_type; #if STXXL_IO_STATS bool running; #endif public: scoped_write_timer(size_type size) #if STXXL_IO_STATS : running(false) #endif { start(size); } ~scoped_write_timer() { stop(); } void start(size_type size) { #if STXXL_IO_STATS if (!running) { running = true; stats::get_instance()->write_started(size); } #else STXXL_UNUSED(size); #endif } void stop() { #if STXXL_IO_STATS if (running) { stats::get_instance()->write_finished(); running = false; } #endif } }; class scoped_read_timer { typedef unsigned_type size_type; #if STXXL_IO_STATS bool running; #endif public: scoped_read_timer(size_type size) #if STXXL_IO_STATS : running(false) #endif { start(size); } ~scoped_read_timer() { stop(); } void start(size_type size) { #if STXXL_IO_STATS if (!running) { running = true; stats::get_instance()->read_started(size); } #else STXXL_UNUSED(size); #endif } void stop() { #if STXXL_IO_STATS if (running) { stats::get_instance()->read_finished(); running = false; } #endif } }; class scoped_wait_timer { #ifndef STXXL_DO_NOT_COUNT_WAIT_TIME bool running; wait_op_type wait_op; #endif public: scoped_wait_timer(wait_op_type wait_op, bool measure_time = true) #ifndef STXXL_DO_NOT_COUNT_WAIT_TIME : running(false), wait_op(wait_op) #endif { if (measure_time) start(); } ~scoped_wait_timer() { stop(); } void start() { #ifndef STXXL_DO_NOT_COUNT_WAIT_TIME if (!running) { running = true; stats::get_instance()->wait_started(wait_op); } #endif } void stop() { #ifndef STXXL_DO_NOT_COUNT_WAIT_TIME if (running) { stats::get_instance()->wait_finished(wait_op); running = false; } #endif } }; public: //! \brief Returns total number of reads //! \return total number of reads unsigned get_reads() const { return reads; } //! \brief Returns total number of writes //! \return total number of writes unsigned get_writes() const { return writes; } //! \brief Returns number of bytes read from disks //! \return number of bytes read int64 get_read_volume() const { return volume_read; } //! \brief Returns number of bytes written to the disks //! \return number of bytes written int64 get_written_volume() const { return volume_written; } //! \brief Returns total number of reads served from cache //! \return total number of cached reads unsigned get_cached_reads() const { return c_reads; } //! \brief Returns total number of cached writes //! \return total number of cached writes unsigned get_cached_writes() const { return c_writes; } //! \brief Returns number of bytes read from cache //! \return number of bytes read from cache int64 get_cached_read_volume() const { return c_volume_read; } //! \brief Returns number of bytes written to the cache //! \return number of bytes written to cache int64 get_cached_written_volume() const { return c_volume_written; } //! \brief Time that would be spent in read syscalls if all parallel reads were serialized. //! \return seconds spent in reading double get_read_time() const { return t_reads; } //! \brief Time that would be spent in write syscalls if all parallel writes were serialized. //! \return seconds spent in writing double get_write_time() const { return t_writes; } //! \brief Period of time when at least one I/O thread was executing a read. //! \return seconds spent in reading double get_pread_time() const { return p_reads; } //! \brief Period of time when at least one I/O thread was executing a write. //! \return seconds spent in writing double get_pwrite_time() const { return p_writes; } //! \brief Period of time when at least one I/O thread was executing a read or a write. //! \return seconds spent in I/O double get_pio_time() const { return p_ios; } //! \brief I/O wait time counter //! \return number of seconds spent in I/O waiting functions //! \link request::wait request::wait \endlink, //! \c wait_any and //! \c wait_all double get_io_wait_time() const { return t_waits; } double get_wait_read_time() const { return t_wait_read; } double get_wait_write_time() const { return t_wait_write; } //! \brief Return time of the last reset //! \return seconds passed from the last reset() double get_last_reset_time() const { return last_reset; } #ifndef STXXL_IO_STATS_RESET_FORBIDDEN //! \brief Resets I/O time counters (including I/O wait counter) _STXXL_DEPRECATED(void reset()); #endif //! \brief Resets I/O wait time counter _STXXL_DEPRECATED(void _reset_io_wait_time()); // for library use void write_started(unsigned_type size_, double now = 0.0); void write_canceled(unsigned_type size_); void write_finished(); void write_cached(unsigned_type size_); void read_started(unsigned_type size_, double now = 0.0); void read_canceled(unsigned_type size_); void read_finished(); void read_cached(unsigned_type size_); void wait_started(wait_op_type wait_op); void wait_finished(wait_op_type wait_op); }; #if !STXXL_IO_STATS inline void stats::write_started(unsigned_type size_, double now) { STXXL_UNUSED(size_); STXXL_UNUSED(now); } inline void stats::write_cached(unsigned_type size_) { STXXL_UNUSED(size_); } inline void stats::write_finished() { } inline void stats::read_started(unsigned_type size_, double now) { STXXL_UNUSED(size_); STXXL_UNUSED(now); } inline void stats::read_cached(unsigned_type size_) { STXXL_UNUSED(size_); } inline void stats::read_finished() { } #endif #ifdef STXXL_DO_NOT_COUNT_WAIT_TIME inline void stats::wait_started(wait_op_type) { } inline void stats::wait_finished(wait_op_type) { } #endif class stats_data { unsigned reads, writes; // number of operations int64 volume_read, volume_written; // number of bytes read/written unsigned c_reads, c_writes; // number of cached operations int64 c_volume_read, c_volume_written; // number of bytes read/written from/to cache double t_reads, t_writes; // seconds spent in operations double p_reads, p_writes; // seconds spent in parallel operations double p_ios; // seconds spent in all parallel I/O operations (read and write) double t_wait; // seconds spent waiting for completion of I/O operations double t_wait_read, t_wait_write; // double elapsed; public: stats_data() : reads(0), writes(0), volume_read(0), volume_written(0), c_reads(0), c_writes(0), c_volume_read(0), c_volume_written(0), t_reads(0.0), t_writes(0.0), p_reads(0.0), p_writes(0.0), p_ios(0.0), t_wait(0.0), t_wait_read(0.0), t_wait_write(0.0), elapsed(0.0) { } stats_data(const stats & s) : reads(s.get_reads()), writes(s.get_writes()), volume_read(s.get_read_volume()), volume_written(s.get_written_volume()), c_reads(s.get_cached_reads()), c_writes(s.get_cached_writes()), c_volume_read(s.get_cached_read_volume()), c_volume_written(s.get_cached_written_volume()), t_reads(s.get_read_time()), t_writes(s.get_write_time()), p_reads(s.get_pread_time()), p_writes(s.get_pwrite_time()), p_ios(s.get_pio_time()), t_wait(s.get_io_wait_time()), t_wait_read(s.get_wait_read_time()), t_wait_write(s.get_wait_write_time()), elapsed(timestamp() - s.get_last_reset_time()) { } stats_data operator + (const stats_data & a) const { stats_data s; s.reads = reads + a.reads; s.writes = writes + a.writes; s.volume_read = volume_read + a.volume_read; s.volume_written = volume_written + a.volume_written; s.c_reads = c_reads + a.c_reads; s.c_writes = c_writes + a.c_writes; s.c_volume_read = c_volume_read + a.c_volume_read; s.c_volume_written = c_volume_written + a.c_volume_written; s.t_reads = t_reads + a.t_reads; s.t_writes = t_writes + a.t_writes; s.p_reads = p_reads + a.p_reads; s.p_writes = p_writes + a.p_writes; s.p_ios = p_ios + a.p_ios; s.t_wait = t_wait + a.t_wait; s.t_wait_read = t_wait_read + a.t_wait_read; s.t_wait_write = t_wait_write + a.t_wait_write; s.elapsed = elapsed + a.elapsed; return s; } stats_data operator - (const stats_data & a) const { stats_data s; s.reads = reads - a.reads; s.writes = writes - a.writes; s.volume_read = volume_read - a.volume_read; s.volume_written = volume_written - a.volume_written; s.c_reads = c_reads - a.c_reads; s.c_writes = c_writes - a.c_writes; s.c_volume_read = c_volume_read - a.c_volume_read; s.c_volume_written = c_volume_written - a.c_volume_written; s.t_reads = t_reads - a.t_reads; s.t_writes = t_writes - a.t_writes; s.p_reads = p_reads - a.p_reads; s.p_writes = p_writes - a.p_writes; s.p_ios = p_ios - a.p_ios; s.t_wait = t_wait - a.t_wait; s.t_wait_read = t_wait_read - a.t_wait_read; s.t_wait_write = t_wait_write - a.t_wait_write; s.elapsed = elapsed - a.elapsed; return s; } unsigned get_reads() const { return reads; } unsigned get_writes() const { return writes; } int64 get_read_volume() const { return volume_read; } int64 get_written_volume() const { return volume_written; } unsigned get_cached_reads() const { return c_reads; } unsigned get_cached_writes() const { return c_writes; } int64 get_cached_read_volume() const { return c_volume_read; } int64 get_cached_written_volume() const { return c_volume_written; } double get_read_time() const { return t_reads; } double get_write_time() const { return t_writes; } double get_pread_time() const { return p_reads; } double get_pwrite_time() const { return p_writes; } double get_pio_time() const { return p_ios; } double get_elapsed_time() const { return elapsed; } double get_io_wait_time() const { return t_wait; } double get_wait_read_time() const { return t_wait_read; } double get_wait_write_time() const { return t_wait_write; } }; std::ostream & operator << (std::ostream & o, const stats_data & s); inline std::ostream & operator << (std::ostream & o, const stats & s) { o << stxxl::stats_data(s); return o; } std::string format_with_SI_IEC_unit_multiplier(uint64 number, const char * unit = "", int multiplier = 1000); inline std::string add_IEC_binary_multiplier(uint64 number, const char * unit = "") { return format_with_SI_IEC_unit_multiplier(number, unit, 1024); } inline std::string add_SI_multiplier(uint64 number, const char * unit = "") { return format_with_SI_IEC_unit_multiplier(number, unit, 1000); } //! \} __STXXL_END_NAMESPACE #endif // !STXXL_IOSTATS_HEADER // vim: et:ts=4:sw=4 stxxl-1.3.1/include/stxxl/bits/io/ufs_file_base.h0000644000175000017500000000272011535151017021626 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/io/ufs_file_base.h * * UNIX file system file base * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2002 Roman Dementiev * Copyright (C) 2008 Andreas Beckmann * Copyright (C) 2009 Johannes Singler * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_UFSFILEBASE_HEADER #define STXXL_UFSFILEBASE_HEADER #include #include __STXXL_BEGIN_NAMESPACE //! \addtogroup fileimpl //! \{ //! \brief Base for UNIX file system implementations class ufs_file_base : public virtual file { protected: mutex fd_mutex; // sequentialize function calls involving file_des int file_des; // file descriptor int mode_; // open mode const std::string filename; ufs_file_base(const std::string & filename, int mode); offset_type _size(); void close(); public: ~ufs_file_base(); offset_type size(); void set_size(offset_type newsize); void lock(); const char * io_type() const; void remove(); }; //! \} __STXXL_END_NAMESPACE #endif // !STXXL_UFSFILEBASE_HEADER stxxl-1.3.1/include/stxxl/bits/io/request_queue_impl_qwqr.h0000644000175000017500000000376711535543650024053 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/io/request_queue_impl_qwqr.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2002 Roman Dementiev * Copyright (C) 2008, 2009 Andreas Beckmann * Copyright (C) 2009 Johannes Singler * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_IO_REQUEST_QUEUE_IMPL_QWQR_HEADER #define STXXL_IO_REQUEST_QUEUE_IMPL_QWQR_HEADER #include #include #include __STXXL_BEGIN_NAMESPACE //! \addtogroup iolayer //! \{ class request_queue_impl_qwqr : public request_queue_impl_worker { private: typedef request_queue_impl_qwqr self; typedef std::list queue_type; mutex write_mutex; mutex read_mutex; queue_type write_queue; queue_type read_queue; state _thread_state; thread_type thread; semaphore sem; static const priority_op _priority_op = WRITE; static void * worker(void * arg); public: // \param n max number of requests simultaneously submitted to disk request_queue_impl_qwqr(int n = 1); // in a multi-threaded setup this does not work as intended // also there were race conditions possible // and actually an old value was never restored once a new one was set ... // so just disable it and all it's nice implications void set_priority_op(priority_op op) { //_priority_op = op; STXXL_UNUSED(op); } void add_request(request_ptr & req); bool cancel_request(request_ptr & req); ~request_queue_impl_qwqr(); }; //! \} __STXXL_END_NAMESPACE #endif // !STXXL_IO_REQUEST_QUEUE_IMPL_QWQR_HEADER // vim: et:ts=4:sw=4 stxxl-1.3.1/include/stxxl/bits/io/request.h0000644000175000017500000000714511535655623020552 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/io/request.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2002 Roman Dementiev * Copyright (C) 2008 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_IO__REQUEST_H_ #define STXXL_IO__REQUEST_H_ #include #include #include #include #include #include #include #include __STXXL_BEGIN_NAMESPACE //! \addtogroup iolayer //! \{ #define BLOCK_ALIGN 4096 class file; class request_ptr; //! \brief Request with basic properties like file and offset. class request : virtual public request_interface { friend class request_ptr; protected: completion_handler on_complete; int ref_cnt; compat_unique_ptr::result error; mutex ref_cnt_mutex; protected: file * file_; void * buffer; offset_type offset; size_type bytes; request_type type; void completed(); public: // returns number of references int nref() { scoped_mutex_lock Lock(ref_cnt_mutex); return ref_cnt; } request(const completion_handler & on_compl, file * file__, void * buffer_, offset_type offset_, size_type bytes_, request_type type_); virtual ~request(); file * get_file() const { return file_; } void * get_buffer() const { return buffer; } offset_type get_offset() const { return offset; } size_type get_size() const { return bytes; } request_type get_type() const { return type; } void check_alignment() const; std::ostream & print(std::ostream & out) const; //! \brief Inform the request object that an error occurred //! during the I/O execution void error_occured(const char * msg) { error.reset(new stxxl::io_error(msg)); } //! \brief Inform the request object that an error occurred //! during the I/O execution void error_occured(const std::string & msg) { error.reset(new stxxl::io_error(msg)); } //! \brief Rises an exception if there were error with the I/O void check_errors() throw (stxxl::io_error) { if (error.get()) throw *(error.get()); } private: void add_ref() { scoped_mutex_lock Lock(ref_cnt_mutex); ref_cnt++; STXXL_VERBOSE3("[" << static_cast(this) << "] request::add_ref(): added reference, ref_cnt=" << ref_cnt); } bool sub_ref() { int val; { scoped_mutex_lock Lock(ref_cnt_mutex); val = --ref_cnt; STXXL_VERBOSE3("[" << static_cast(this) << "] request::sub_ref(): subtracted reference, ref_cnt=" << ref_cnt); } assert(val >= 0); return (val == 0); } protected: void check_nref(bool after = false) { if (nref() < 2) check_nref_failed(after); } private: void check_nref_failed(bool after); }; inline std::ostream & operator << (std::ostream & out, const request & req) { return req.print(out); } //! \} __STXXL_END_NAMESPACE #endif // !STXXL_IO__REQUEST_H_ // vim: et:ts=4:sw=4 stxxl-1.3.1/include/stxxl/bits/io/wfs_file_base.h0000644000175000017500000000322311535151017021627 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/io/wfs_file_base.h * * Windows file system file base * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2005 Roman Dementiev * Copyright (C) 2008, 2010 Andreas Beckmann * Copyright (C) 2009, 2010 Johannes Singler * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_WFSFILEBASE_HEADER #define STXXL_WFSFILEBASE_HEADER #ifdef STXXL_BOOST_CONFIG #include #endif #ifdef BOOST_MSVC #include #include #include __STXXL_BEGIN_NAMESPACE //! \addtogroup fileimpl //! \{ //! \brief Base for Windows file system implementations class wfs_file_base : public virtual file { protected: mutex fd_mutex; // sequentialize function calls involving file_des HANDLE file_des; // file descriptor int mode_; // open mode const std::string filename; offset_type bytes_per_sector; bool locked; wfs_file_base(const std::string & filename, int mode); offset_type _size(); void close(); public: ~wfs_file_base(); offset_type size(); void set_size(offset_type newsize); void lock(); const char * io_type() const; void remove(); }; //! \} __STXXL_END_NAMESPACE #endif // #ifdef BOOST_MSVC #endif // !STXXL_WFSFILEBASE_HEADER stxxl-1.3.1/include/stxxl/bits/io/wincall_file.h0000644000175000017500000000355211535151017021474 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/io/wincall_file.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2005-2006 Roman Dementiev * Copyright (C) 2008 Andreas Beckmann * Copyright (C) 2009, 2010 Johannes Singler * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_WINCALL_FILE_HEADER #define STXXL_WINCALL_FILE_HEADER #ifndef STXXL_HAVE_WINCALL_FILE #ifdef STXXL_BOOST_CONFIG #include #endif #ifdef BOOST_MSVC #define STXXL_HAVE_WINCALL_FILE 1 #else #define STXXL_HAVE_WINCALL_FILE 0 #endif #endif #if STXXL_HAVE_WINCALL_FILE #include #include __STXXL_BEGIN_NAMESPACE //! \addtogroup fileimpl //! \{ //! \brief Implementation of file based on Windows native I/O calls class wincall_file : public wfs_file_base, public disk_queued_file { public: //! \brief constructs file object //! \param filename path of file //! \attention filename must be resided at memory disk partition //! \param mode open mode, see \c stxxl::file::open_modes //! \param disk disk(file) identifier wincall_file( const std::string & filename, int mode, int queue_id = DEFAULT_QUEUE, int allocator_id = NO_ALLOCATOR) : wfs_file_base(filename, mode), disk_queued_file(queue_id, allocator_id) { } void serve(const request * req) throw (io_error); const char * io_type() const; }; //! \} __STXXL_END_NAMESPACE #endif // #if STXXL_HAVE_WINCALL_FILE #endif // !STXXL_WINCALL_FILE_HEADER stxxl-1.3.1/include/stxxl/bits/compat_hash_map.h0000644000175000017500000000407211535151017021556 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/compat_hash_map.h * * compatibility interface to C++ standard extension hash_map * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2008, 2010 Andreas Beckmann * Copyright (C) 2009, 2010 Johannes Singler * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_HEADER__COMPAT_HASH_MAP_H_ #define STXXL_HEADER__COMPAT_HASH_MAP_H_ #if defined(__GXX_EXPERIMENTAL_CXX0X__) #include #elif defined(BOOST_MSVC) #include #elif defined(__GNUG__) && ((__GNUC__ * 10000 + __GNUC_MINOR__ * 100) >= 40200) && \ (!defined(__ICC) || (__ICC > 1200)) #include #else #include #endif #include __STXXL_BEGIN_NAMESPACE template struct compat_hash { #if defined(__GXX_EXPERIMENTAL_CXX0X__) typedef std::hash<_Tp> result; #elif defined(BOOST_MSVC) typedef stdext::hash_compare<_Tp> result; #elif defined(__GNUG__) && ((__GNUC__ * 10000 + __GNUC_MINOR__ * 100) >= 40200) && \ (!defined(__ICC) || (__ICC > 1200)) typedef std::tr1::hash<_Tp> result; #else typedef __gnu_cxx::hash<_Tp> result; #endif }; template ::result> struct compat_hash_map { #if defined(__GXX_EXPERIMENTAL_CXX0X__) typedef std::unordered_map<_Key, _Tp, _Hash> result; #elif defined(BOOST_MSVC) typedef stdext::hash_map<_Key, _Tp, _Hash> result; #elif defined(__GNUG__) && ((__GNUC__ * 10000 + __GNUC_MINOR__ * 100) >= 40200) && \ (!defined(__ICC) || (__ICC > 1200)) typedef std::tr1::unordered_map<_Key, _Tp, _Hash> result; #else typedef __gnu_cxx::hash_map<_Key, _Tp, _Hash> result; #endif }; __STXXL_END_NAMESPACE #endif // !STXXL_HEADER__COMPAT_HASH_MAP_H_ stxxl-1.3.1/include/stxxl/bits/version.h0000644000175000017500000000126111026753412020117 0ustar andreasandreas/*************************************************************************** * include/stxxl/bits/version.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2007 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_VERSION_HEADER #define STXXL_VERSION_HEADER #include __STXXL_BEGIN_NAMESPACE const char * get_version_string(); __STXXL_END_NAMESPACE #endif // !STXXL_VERSION_HEADER stxxl-1.3.1/include/stxxl/ksort0000644000175000017500000000077011026753412016411 0ustar andreasandreas/*************************************************************************** * include/stxxl/ksort * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2007 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #include stxxl-1.3.1/include/stxxl/vector0000644000175000017500000000100011026753412016534 0ustar andreasandreas/*************************************************************************** * include/stxxl/vector * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2007 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #include stxxl-1.3.1/include/stxxl/deque0000644000175000017500000000077611026753412016360 0ustar andreasandreas/*************************************************************************** * include/stxxl/deque * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2007 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #include stxxl-1.3.1/include/stxxl/types0000644000175000017500000000077711032431155016414 0ustar andreasandreas/*************************************************************************** * include/stxxl/types * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2008 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #include stxxl-1.3.1/include/stxxl/stack0000644000175000017500000000077611026753412016362 0ustar andreasandreas/*************************************************************************** * include/stxxl/stack * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2007 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #include stxxl-1.3.1/include/stxxl/io0000644000175000017500000000076011026753412015655 0ustar andreasandreas/*************************************************************************** * include/stxxl/io * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2007 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #include stxxl-1.3.1/include/stxxl/all0000644000175000017500000000074611026753412016022 0ustar andreasandreas/*************************************************************************** * include/stxxl/all * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2007 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #include stxxl-1.3.1/include/stxxl/map0000644000175000017500000000077211026753412016026 0ustar andreasandreas/*************************************************************************** * include/stxxl/map * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2007 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #include stxxl-1.3.1/include/stxxl/aligned_alloc0000644000175000017500000000101711032431155020011 0ustar andreasandreas/*************************************************************************** * include/stxxl/aligned_alloc * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2008 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #include stxxl-1.3.1/include/stxxl.h0000644000175000017500000000175111504161427015475 0ustar andreasandreas/*************************************************************************** * include/stxxl.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2002-2007 Roman Dementiev * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_MAIN_HEADER #define STXXL_MAIN_HEADER #include #include #include #include #include #include #if ! defined(__GNUG__) || ((__GNUC__ * 10000 + __GNUC_MINOR__ * 100) >= 30400) // map does not work with g++ 3.3 #include #endif #include #include #include #include #include #include #endif // STXXL_MAIN_HEADER stxxl-1.3.1/Makefile.msvc0000644000175000017500000000460411535151017015124 0ustar andreasandreas# This -*- Makefile -*- is intended for processing with nmake. ############################################################################ # Makefile.msvc # # Part of the STXXL. See http://stxxl.sourceforge.net # # Copyright (C) 2005-2007 Roman Dementiev # Copyright (C) 2009, 2010 Johannes Singler # # Distributed under the Boost Software License, Version 1.0. # (See accompanying file LICENSE_1_0.txt or copy at # http://www.boost.org/LICENSE_1_0.txt) ############################################################################ main: library TOPDIR=$(MAKEDIR) include make.settings library: cd common $(MAKE) TOPDIR="$(MAKEDIR)" lib cd .. cd io $(MAKE) TOPDIR="$(MAKEDIR)" lib cd .. cd mng $(MAKE) TOPDIR="$(MAKEDIR)" lib cd .. cd algo $(MAKE) TOPDIR="$(MAKEDIR)" lib cd .. cd lib $(MAKE) TOPDIR="$(MAKEDIR)" cd .. cd common $(MAKE) TOPDIR="$(MAKEDIR)" tools cd .. cd utils $(MAKE) TOPDIR="$(MAKEDIR)" tools cd .. cd io $(MAKE) TOPDIR="$(MAKEDIR)" tools cd .. @echo "Building library is completed." @echo "Use the following compiler options with programs using Stxxl: $(STXXL_COMPILER_OPTIONS)" @echo "Use the following linker options with programs using Stxxl: $(STXXL_LINKER_OPTIONS)" @echo $(STXXL_COMPILER_OPTIONS) > compiler.options @echo $(STXXL_LINKER_OPTIONS) > linker.options tests: library cd common $(MAKE) TOPDIR="$(MAKEDIR)" tests cd .. cd io $(MAKE) TOPDIR="$(MAKEDIR)" tests cd .. cd mng $(MAKE) TOPDIR="$(MAKEDIR)" tests cd .. cd containers $(MAKE) TOPDIR="$(MAKEDIR)" tests cd .. cd algo $(MAKE) TOPDIR="$(MAKEDIR)" tests cd .. cd stream $(MAKE) TOPDIR="$(MAKEDIR)" tests cd .. cd utils $(MAKE) TOPDIR="$(MAKEDIR)" tests cd .. @echo "Building tests is completed." @echo "Use the following compiler options with programs using Stxxl: $(STXXL_COMPILER_OPTIONS)" @echo "Use the following linker options with programs using Stxxl: $(STXXL_LINKER_OPTIONS)" clean: cd lib $(MAKE) TOPDIR="$(MAKEDIR)" clean cd .. cd common $(MAKE) TOPDIR="$(MAKEDIR)" clean cd .. cd io $(MAKE) TOPDIR="$(MAKEDIR)" clean cd .. cd mng $(MAKE) TOPDIR="$(MAKEDIR)" clean cd .. cd containers $(MAKE) TOPDIR="$(MAKEDIR)" clean cd .. cd algo $(MAKE) TOPDIR="$(MAKEDIR)" clean cd .. cd stream $(MAKE) TOPDIR="$(MAKEDIR)" clean cd .. cd utils $(MAKE) TOPDIR="$(MAKEDIR)" clean cd .. @echo "Cleaning completed" stxxl-1.3.1/stxxl.suo0000644000175000017500000041300011046361576014433 0ustar andreasandreasࡱ>   #!$- "&%'6()*+,.?/0123457P8O:C=>@AzEFGHIJRNMTQq[S9VW]YdK\n_`kcefgUlmyoprustv|wxB{}j~Root Entry)GMProjInfoExTaskListUserTasks$IVSMDPropertyBrowser*R H-39$%&'()*+./01275:`;=@ABCDEFJ]YKLMNOPQRSTUVWXZ[\^_wcegiknprsvxy|~a[`NC~uC Device ControlsCrystal ReportsData XML Schema Dialog EditorMobile Web Forms Web Forms Components Windows FormsHTMLClipboard RingGeneralC:\stxxl\IToolboxService DebuggerWatches DebuggerBreakpoints( DebuggerExceptions&xC:\Programme\Microsoft Visual Studio .NET 2003\Vc7\crt\src\C:\Programme\Microsoft Visual Studio .NET 2003\Vc7\atlmfc\src\mfc\C:\Programme\Microsoft Visual Studio .NET 2003\Vc7\atlmfc\src\atl\8c:\stxxl\conDebuggerFindSource& ^DebuggerFindSymbol&DebuggerMemoryWindows,TExternalFilesProjectContents:ST>C:\stxxl\stxxl.vcproj<open> tͫ4-. ͫ4MultiStartupProj=;4{26082884-8591-49FC-BA2E-471EA5236214}.dwStartupOpt=;StartupProject=&{26082884-8591-49FC-BA2EDocumentWindowPositions0DocumentWindowUserData. SolutionConfiguration,ObjMgrContents T-471EA5236214};A{26082884-8591-49FC-BA2E-471EA5236214}.Library|Win32.BatchBldCtx= Debug|Win32;?{26082884-8591-49FC-BA2E-471EA5236214}.Library|Win32.fBatchBld=;K{26082884-8591-49FC-BA2E-471EA5236214}.Library and tests|Win32.BatchBldCtx=LibraryNSܾ M%y%ү##G}'bm4l #O¤EQ ,C:\stxxl\stxxl.vcproj,C:\s$Bookmarks V001.01\async_sched0Library and tests|Win32DebugSettings... ....... .,GeneralConfigSettings(EndConfigPropertiesLibrary|ClassViewContents$ProjExplorerState$!UnloadedProjects"stxxl #@Win32DebugSettings... ....... .,GeneralConfigSettings(EndConfigPropertiesX and tests|Win32;I{26082884-8591-49FC-BA2E-471EA5236214}.Library and tests|Win32.fBatchBld=TaskListShortcuts$,IDiscoveryService$.rResEdit.optProperty Manager"`;4{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}.dwStartupOpt=; ActiveCfg=Library and tests|Wi stxxl471EA5236214}.Debug|Wijc:\stxxl\include\stxxl\bits\containers\btree\btree.hsBxc:\stxxl\include\stxxl\bits\conn32;Cfg=Library and tests|Wi32;ͫ4ͫ4txxl\stxxl.vcprojHeader Filetainers\btree\iterator_map.hғ;6ry }hc:\stxxl\include\stxxl\bits\containers\btree\leaf.h-D7 `ͫ4ᆳͫ4ᆳ)8c:\stxxl\containers\stack.hOutliningStateDir$B=BookmarkState"(OutliningState1 !>OutliningState7 $?0i S{|<~-#L)"#  #$%UIWg%qt*x{+E m7e:\programme\microsoft visual studio 8\vc\include\xhash5e:\programme\microsoft visual studio 8\vc\include\new:E:\Programme\Microsoft Visual Studio 8\VC\include\xutility8e:\programme\microsoft \crt_bld\self_x86\crt\src\crtexe.crF:\RTM\vctools\crt_bld\SELF_X86\crt\src\intel\chkstk.asm6sSource Fileseader File\c:\stxxl\include\stxxl\bits\cPc:\stxxl\include\stxxl\bits\io\iobase.h|?]5^|Hc:\stxxl\include\stxxl\bits\io\io.hnrV+>c:\stxxl\utils\createdisks.cppn @c:\stxxl\io\benchmark_disks.cpp'Rc:\stxxl\containers\test_ext_merger2.cppq3 Jc:\stxxl\containers\monotonic_p\c:\stxxl\include\stxxl\bits\io\boostfd_file.hw1b" Vc:\stxxl\include\stxxl\bits\com (* 09 ;MWYce>g)i# ,2O #$%02>4.6P4-8591-49FC-BA2E-471EA523621mon\mutex.hv*r Rc:\stxxl\include\stxxl\bits\common\log.hן  '"&*'+),2ECSPDHLPQ!q>LastOpenTemporarilyOfflineData EndOfStream1c:\stxxl\mng\test_mng1.cppdf:\rtm\vctools\crt_bld\self_x86\crt\src\dbghook.c {ommon\settings.hpc:\stxxl\inc2c:\stxxl\io\wfs_file.cpp9Bme\microsof:c:\stxxl\io\wincall_file.cpp-=rosoft 2c:\stxxl\io\ufs_file.cpp=dl   ' >'+!=A2DG2HIJOPVW4E\ECSP22C2A22}1234l ȌECSPle:\programme\microsoft viq.cppVc:\stxxl\include\stxxl\bits\common\utils.h](14c:\stxxl\io\diskqueue.cpp~ T-\!$"%&'])!,/23Rc:\stxxl\containers\test_many_stacks.cpp5!Nc:\stxxl\containers\test_iterat4c:\stxxl\mng\write_pool.hIy A*"+"./B0B;C0DIKQTjo3t4u{}N~&c:\stxxl\mng\mng.hI4,0*9=X?FIAMAPSAVYH]cgmpv y   * /, A%&*@,//>J8LO.QU\efip |~ s#N3''*<7 G%jt v @o  71!" $*%()#*4+/0/1 7DKLOQ"T!>]9_a5fjlmpqtuxgz{5| }5 5 5A*,<;=@6GNOU]>aPc:\stxxl\containers\test_map_random.cpp'Nk Bc:\stxxl\containers\test_map.cpp>>OutliningState13"`OutliningState3 "#OutliningState2 VOutliningState4 Vors.cpp2(u$ .<094<?4BG!IY*c:\stxxl\io\iobase.hxPc:\stxxl\containers\test_migr_stack.cpp*tD ?365922C2A22} ;Fc:\stxxl\containers\test_queue.VsToolboxService"EGXmlPackageOptions$IObjMgrContentsV8"8HiddenSlnFolders"%tainers\stack.hbf:\rtm\vctools 6e:\programme\microsoft visual studio 8\vc\include\listQ\]`adeijn#o  Z1"%  ##%DEKLR_ fhcpp\ 0 Hc:\stxxl\containers\test_pqueueFc:\stxxl\containers\test_deque.cpp I  d8c:\stxxl\containers\deque.h7M6 "'4<1>F HK MP#RV#X\^acOutliningState6 LOutliningState9 OutliningState10"*(OutliningState11" ghkmprvw|}""!,,+B<'+  ##  "" !!%('+&,1%269:&E\<]\aeq tvx| ~%)pe:\programme\microsoft visual studio 8\vc\include\xhash<ne:\programme\microsoft visual studio 8\vc\include\listh4   A! $6/-;>ABE0<IL2MN/O\dbghook.cJRY6\fDgh&ip#qr,s{4c:\stxxl\io\mmap_file.cppA43-11D0-AE1A-00A0C90FFFC3}|<Mi#|},~B%visual studio 8\vc\include\vector9e:\programme\microsoft visual studio 8\vc\include\xstring8e:\programme\microsoft visual studio 8\vc\include\memory:e:\programme\microsoft visual studio 8\vc\include\iteratorC:\stxxl\stxxl.vcproj9e:\programme\microsoft visual studio 8\vc\include\xmemoryu"+"+%S:\stxxl\containers\monotonic_p_abe7]hkmnr iu'v<%$),04,ANc:\stxxl\containers\btree\node_cache.hq%   h !"#$%&'()*+,-./0123456789:;<=\?@ABCDEFGHIJKLMOPQRbTUVWXYZ[]^_`abcefgjmnoqrstuvwxyz{|}~?3618,;@>BE F+JA+J9LSNT UQV-jq w/ ?kKm)+/(168K*M[\efi7qt mvvD8H,SVLY(<c:\stxxl\algo\test_ksort1.cpps"k B!4&)*-.1"4659 :pmemory:c:L)=Rc:\stxxl\include\stxxl\bits\io\iostats.h7 ,34c:\stxxl\common\debug.cpp'bO 0  )2c:\stxxl\common\seed.cpp b,lp,qu%vz%;6"0FQQQ Y*#*$().'07/78 9=CD UX5Z^Y^0`d_dfiei*ty@z~l~H! (;!4>#$   +  "&'+,014!47; <@AEFJ KO*PXY]^b cghlmqrvw{|! (;=/26@9113  )  0(,- )=CD>Q+RZ^bcd<[o0qBc:\stxxl\containers\btree\leaf.hH&(*OutliningState12"' >OutliningState5 /OutliningState8 XOutliningState22"NR/15>KNEO 6W)-&  & "%',-0acfhkmp.r.$*+1+1&%E'G'*c:\stxxl\mng\mng.cpp5*!"0:OIAN#ME#RJ#L!##/15N6:<@#BNPTPUYLZ^3_cei$lt2uyQz~52OE13 #) C/#'2-:=@BFI&BESIMfBsk@15>6;@A.=H1IMQR=NX=Y]ab<^i<jn=os=tx:|{  '+''&(&(:8:8G+!   /3#4859>7?D#FK6MR?TZA\` aefjkoquvz+pz|{ 3 #+%(; = sE),:#9%),03:A9D>MRWX'Y N_dkln0`s tx y4,//7'7      & !#.".07/7(;?;AE=GL/MQ2RX@Y]9_cf<H9; 8)J!%/91[,?TEIHORJR!Z_-ko/pt>uz0{2c@!      !"#$%&'()*+,-./0123456789:;<=>@ABCDEFGHJLNPRTVWXYZ[\]^_`abcdehjlnpruwy{}te:\programme\microsoft visual studio 8\vc\include\xstring@_  +@,526K7:+/:,=AYENBNZQZOZ8^b[bhpqv)e{(|&(&(:8:8A>7766774  "%7,0&BESIMFMTPTNT2X[U[5aeKfi+^i)lp(qu&v{(|&(:8:8D>51 4 -  N"#([!(J-6+6K9B7B)D<IN4OUW]_eEflXms3tzF{=PIG8KSK\*+\J]TgOb 7,!).3#,AEJKBPTYMQ_#`d7jn6os.tx8y}7~/4$E3=8JMKM4$C3 = 8J"M$(K)-M.2D3789R&TgChln~4?MH[]3C TG50S15ndlers.h@LTNO`c:\stxxl\containers\leda_sm_stack_benchmark.cpp6nNoZc:\stxxl\containers\leda_sm_pq_benchmark.cppya~Dc:\stxxl\containers\copy_file.cpp]:!8/\c:\stxxl\include\stxxl\bits\io\/14/69#;X)Zw*y0*0>J %Q%SX]^Zd4fikw/z+)   ``"%`03`>A`LO`Y\_emp crr68>2?4_   .! #$()-.12569:=wincall_file.hmF! ! \c:\stxxl\containers\berkeley_db0c:\stxxl\common\log.cpp,b\c:\stxxl\containers\btree\test_const_scan.cppZP B$Q%*+01>?L!M;<BDIK)Lx (1-le:\programme\microsoft visual studio 8\vc\include\newZ  * !("4#'*&A+C9=?>@OutliningState28";S OutliningState26" OutliningState23"6pOutliningState19"05R7@EEIAJL#CLT?`4efimo psvT6VZ[_&   01=2flm~" $ -7OVPUW\U]bdilq*tx/{.0$*"(-3+106.8.>) GM#+#%-(,(-1'26&7;$<@(AF3GK>LS(TX7Yb cgk)l'jo'q{+|J#tumigr_stack.cppVc:\stxxl\include\stxxl\bits\common\debug.hW  fc:\stxxl\include\stxxl\bits\common\aligned_alloc.hxDLc:\stxxl\include\stxxl\bits\ver:c:\stxxl\io\syscall_file.cppZ SourceCodeControl$utSccProviderRegKey$HOutliningState47"4zOutliningState50"b`pat_hash_map.h^-U\c:\stxxl\include\stxxl\bits\comhc:\stxxl\include\stxxl\bits\containers\btree\node.htc:\stxxl\include\stxxl\bits\containers\btree\node_cache.h>aD(vc:\stxxl\include\stxxl\bits\conOutliningState49"MW<xOutliningState48"P6OutliningState44"OutliningState43"QNre:\programme\microsoft visual studio 8\vc\include\vectorqm  &@'5-1K25+*58;>BDDJCJDLRKR#TWSW]deLgZlmqryz'%'%Q.+Q$$Q##$$!/0 Vc:\stxxl\include\stxxl\bits\algo\adaptor.h}Vr"sw\c:\stxxl\include\stxxl\bits\com2c:\stxxl\common\rand.cpp33:c:\stxxl\io\boostfd_file.cppg ~-'@0?""""" 9%'"2, \stx "Tc:\stxxl\include\stxxl\bits\common\rand.h"*'Pc:\stxxl\containers\map_test_hae!f-n7tW?)pat_auto_ptr.h_ e8`c:\stxxl\include\stxxl\bits\algtainers\btree\btree_pager.h Ȭode.h.zc:\Program Files\Micrc:\stxxl\include\stxxl\bits\containers\btree\root_node.hۺ8 +o\stable_ksort.h8  / ist Dc:\stxxl\containers\@c:\stxxl\common\simple_vector.h4c:\stxxl\containers\map.hט4@nWpsuwWz~LL63.#* !'#(.(.=I*(   HK[UY\bf\os\|\\ 214}|stxxl.vcproj|c:\stxxl"c:\stxxl\io\io.hWM`%365922C2A"$&'+1678IJLMOPTX\]de\stxxl\bits\mng\buf_writer.hmrc:\stxxl\include\stxxl\bits\containers\btree\root_node.h.Rc:\stxxl\containers\btree\test_btree.cppzc:\Program Files\Microsoft Visual Studio 8\VC\include\math.h6<c:\stxxl\utils\off_t_size.cpp4c:\stxxl\mng\unittest.cppV2c:\stxxl\common\seed.cpp?0c:\stxxl\common\log.cpp\c:\stxxl\include\stxxl\bits\io\syscall_file.ht\c:\stxxl\include\stxxl\bits\compat_hash_set.h2c:\stxxl\io\wfs_file.cppRHc:\stxxl\algo\test_stable_ksort.cppdZc:\stxxl\include\stxxl\bits\,  5!%K&)+),/@1505@7;6;=@<@CGHLMRSYZ_`f'gl%mr'sw%x}1~+&# #"*=#6>#5 #)*$$JabKjkoquvz{+p  * #+%  & !#.".07/7(;?;AE=GL/MQ2RX@Y]9_cfjmrx3~))3u  OutliningState39"AOutliningState40"8OutliningState45"OLOutliningState41"D-).4.4--#&*Fc:\stxxl\containers\test_stack.$*+9=U,V] tcCfkCmg214}|stxxl.vcproj|c:\stxxl1 POutliningState30",>OutliningState31",POutliningState32"=1OutliningState37"C"~C; //ZZ/ F     @!#h$!%(),24<> ?(@CE F/GJMPS*T[_ `dYfin ougyzL|6#&#3#)538K$j3I?V2BVEntvwy'o340c:\stxxl\common\utils.hh  '4(+*,FJKLQUVWZ^_`kl"uyz/{|6}o* 3 78;@FG(IJ*LY,Z[\_.`abgo svw{p{!#~",9,/(4"(811)  )Z\_bcf ]iGmp4kr s J.cppt2ntainers\test_pqueueOutliningState18"2XOutliningState17"bOutliningState16"418OutliningState15" (Pc:\stxxl\containers\test_ext_merger.cppϺ5&.!Pc:\stxxl\containers\stack_benchmark.cppG3QX&[Jc:\stxxl\containers\pq_benchmarBc:\stxxl\algo\async_schedule.cppH# dj8c:\stxxl\common\version.cppn_B""6  "%4)0I48':>*?C-DHQUVZ[_'`h<imNq| $-6 $   Rc:\stxxl\containers\btree\iterator_map.h-U %?),'-214.5,FMQSOutliningState14"&3ROutliningState20"FOutliningState21")+OutliningState27"-Dv6c:\stxxl\mng\test_mng1.cpp@ te:\programme\microsoft visual studio 8\vc\include\xmemory_,   0#-2169=?BDHKO"RVhl mq,rvwz+{~/5)#7.!YKK+/5.:re:\programme\microsoft visual studio 8\vc\include\memoryD7U  $")%);.>8BL_QTMTCY^HdtAy47;%V2!!Hc:\stxxl\containers\test_vectorPc:\stxxl\containers\btree\btree_pager.hy"'# ,. 1 2 7;1<"8 AB2B0!"%  +!*"&-'.'04+6<>>C.EI:JO=PX Y]a/c!^j"koptu{|MKTR!!ve:\programme\microsoft visual sOutliningState25"97 OutliningState24"DOutliningState33"<@OutliningState29" ntudio 8\vc\include\iterator  1,$.%)/*.1/37B:>2JN,PU/VZ0[_2`dAhDkoI{,)*-rF@&++ = ='@(,07<=/>B1C3DH4IM6NRTX\5w{K|(%? >>==>>'%'% . ^L;Z<hiba+ !c%5;?K@DGKFLSTXY]$^c$dh#in#os$tx$y}~%'%'%@+ (vE:\Programme\Microsoft Visual Studio 8\VC\include\xutility k  &@'5,UZ.[w}E9M P ISDc:\stxxl\containers\btree\btree.h&x:4KPEm G*lz8*,    !"#$%&'()*q-./0r23456789:;<=>?@ABCDFGHIJmMNOPQRSTUVWXYZ[\]^_`abcdefghijklnop~tuvwxyz|}0c:\stxxl\algo\adaptor.hq͊A#%(++,34< =D&EMO `bhkor0s|}%+-T+%/0   2!'(7-8<BC =K9MR9TY^8a))$[@2 2<!#.".A    /MQ2pc:\stxxl\include\stxxl\bits\containers\btree\iterator.hҲqBsxBz~CC8$$$$ $ $C  !#.@/2668>2?E7E6GM2NTFT6VZ[_U_eijnosuy2z+t)$A/ `K+,.,.@*>+0>A$BE*FIJ"QT MVV"QT MV8c:\stxxl\containers\pager.hM#:c:\stxxl\containers\vector.hJTO"#(*+\]2be#hj#lp qt.OutliningState35"BLOutliningState36":?KLOutliningState34"OutliningState38"+Xvy9{~!!$$!##"..-?>) ",$&#(, -0.2537:!<?!AD$FJ$LPRUWZ\_aefklpqv#w{#|"(('.P<*+./K3NO*aBb PcLg hv'w|}-7+F*0  "8$)>*/70>8?M%N%()-/ ?CEHINQ#ROW2Y"be ^g.cpp( Sramme\microsoft visual s "#'='?'({2|9( 0) 'containers\map.h9Dc:\stxxl\mng\test_buf_streams.cppBc:\stxxl\containers\test_map.cpp\c:\stxxl\include\stxxl\bits\io\wincall_file.hN^c:\stxxl\include\stxxl\bits\containers\deque.h}`c:\stxxl\include\stxxl\bits\containers\vector.hxVc:\stxxl\inclOutliningState66"a^BOutliningState69"\ZmlOutliningState67"_rOutliningState68"\async_schedule.cppve:\programme\microsoft visual studio 8\vc\include\iteratorle:\programme\microsoft visual studio 8\vc\include\newRc:\stxxl\include\stxxl\bits\common\log.h^c:\stxxl\include\stxxl\bits\containers\queue.hzZc:\stxxl\include\stxxl\bits\mng\write_pool.hi2c:\stxxl\io\unittest.cppWVc:\stxxl\mng\test_block_alloc_strategy.cppPc:\stxxl\include\stxxl\bitor.hA8c:\stxxl\containeBc:\stxxl\stream\test_stream1.cpXc:\stxxl\include\stxxl\bits\stream\stream.hJ0 ude\stxxl\bits\common\timer.hJc:\stxxl\containers\write_vector.cpp]8c:\stxxl\containers\stack.hTc:\stxxl\include\stxxl\bits\io\ufs_file.hstc:\stxxl\include\stxxl\bits\mng\block_alloc_interleaved.h\c:\stxxl\include\stxxl\bits\mng\buf_ostream.h##  ''6c:\stxxl\io\syscall_file.h}'+=*>.CIfile.h} GO $N&*58 /<n@c:\stxxl\stream\test_stream.cppRc:\stxxl\containers\btree\iterator_map.h"dc:\stxxl\include\stxxl\bits\algo\random_shuffle.h80c:\stxxl\io\test_io.cpp0c:\stxxl\io\sd_test.cppTc:\stxxl\include\stxxl\bits\noncopyable.h\c:\stxxl\containers\btOutliningState83"VOutliningState106$OutliningState107$mp~OutliningState105$n?r7AAC2DE.GK/LP(RXZ ]9`a.dWfjmrs&vd/./ )  x.#l.#ree\test_const_scan.cpp_Hc:\stxxl\mng\test_prefetch_pool.cppUvc:\stxxl\include\stxxl\bits\containers\btree\btree_pager.h,@c:\stxxl\common\test_random.cpp4c:\stxxl\common\debug.cpp=Bc:\stxxl\mng\test_write_pool.cppRc:\stxxl\containers\test_man\c:\stxxl\include\stxxl\bits\common\settings.hpc:\stxxl\include\stxxl\bits\containers\priority_queue.h{Bc:\stxxl\algo\async_schedule.cppve:\programme\microsoft visual studio 8\vc\include\iteratorle:\programme\microsoft visual studio 8\vc\include\newRc:\stxxl\include\stxxl\bits\common\log.h^c:\stxxl\include\stxxl\bits\containers\queue.hzZc:\stxxl\include\stxxl\bits\mng\write_pool.hi2c:\stxxl\io\unittest.cppWVc:\stxxl\mng\test_block_alloc_strategy.cppPc:\stxxl\include\stxxl\bits\namespace.hre:\programme\microsoft visual studio 8\vc\include\memoryDc:\stxxl\algo\test_manyunits1.cppXc:\stxxl\include\stxxl\bits\algo\intksort.h:c:\stxxl\io\boostfd_file.cppCTc:\stxxl\include\stxxl\bits\mng\adaptor.hq~c:\Program Files\Microsoft Visual Studio 8\VC\include\xutility5dc:\stxxl\include\stxxl\bits\algo\async_schedule.h`c:\stxxl\include\stxxl\bits\algo\stable_ksort.hf<c:\stxxl\algo\test_ksort1.cppFc:\stxxl\stream\test_push_sort.cppjc:\stxxl\containers\btree\test_coOutliningState46"JOutliningState42"Gx164B10B9-B200-11D0_ProjState: tE6FDF8B0-F3D1-11D4_ProjState:rr_insert_erase.cppfc:\stxxl\include\stxxl\bits\mng\block_prefetcher.hp\c:\stxxl\include\stxxl\bits\mng\buf_istream.hoLc:\stxxl\containers\write_vector2.cpp^:c:\stxxl\io\flushbuffers.cppZ>c:\stxxl\common\stxxl_info.cppVc:\stxxl\include\stxxl\bits\common\tuple.h~Bc:\stxxl\stream\test_stream1.cppSVc:\stxxl\include\stxxl\bits\algo\adaptor.hA8c:\stxxl\containers\pager.h$Pc:\stxxl\containers\test_map_random.cpp re:\programme\microsoft visual studio 8\vc\include\vectorFc:\stxxl\containers\test_queue.cpppe:\programme\microsoft visual studio 8\vc\include\xhash Lc:\stxxl\algo\test_random_shuffle.cppVc:\stxxl\include\stxxl\bits\common\tmeta.h`c:\stxxl\include\stxxl\bits\common\exceptions.h^c:\stxxl\include\stxxl\bits\containersrg2 !.#*/+24?A G,H O#Q#Y_#gmnXsKuYhY("+XQ#"+$% '&46478.:>/?C)EJL O)QR.T;VZ[\]*g/./" o:../" U:=./ "  U :(L=@.BF/GK"MXZ ]U-`a:j[./" Up: ./" U* #.%)/*.#0?A EHI3N dl.nr/sw#y JP3 ./# J3 ./# J3$ IL.NR/SW#Ygi mJ,prtuQz./ |Q./ Q./   Q"36.8</=ACMO R$TUQZkn.pt/uy{ \Q./ >< /7  &/   o\syscall_file.cppDrc:bc:\stxxl\include\stxxl\bits\stream\sort_stream.hb  !0(4789I< = G$IJLPn)tu){?j]E\ 2) V#6 L$L))?   ]9$%*+(,)-Z[\] e2f)^ jmn-s uyzL19;)\) >1:78B7STIZ!~5$B '"%" B% '!*/S2!8+9'@.A!M.NY%Z hkY3 !H! $ ./F^GKEV]>_`./ ?"/S@  .Zc:\stxxl\include\stxxl\bits\mng\write_pool.h E13)56D7F=G4HNOVXmopq5v7wP;')$ 9"/FAE04EC1-301F-11D3_ProjState:OutliningState64"Y]dXOutliningState60"XbOutliningState62"UfOutliningState61"DOutliningState63"BOutliningState71"[bOutliningState70"of  22}1234`c:\stxxl\include\stxxl\bits\mng\prefetch_pool.hUH71EA5236Lc:\stxxl\include\stxxl\bits\mng\mng.h=kZjcontainers\btree\rZc:\stxxl\include\stxxl\bits\mng\buf_writer.h4d \c:\stxxl\include\stxxl\bits\mngOutliningState108$IpOutliningState52"KK\OutliningState109$otMjOutliningState110$Ol\buf_ostream.h@i.h||{D0E1A\c:\stxxl\include\stxxl\bits\mng\buf_istream.h ,fc:\stxxl\include\stxxl\bits\mng\block_prefetcher.hpl\incTc:\stxxl\include\stxxl\bits\mng\adaptor.hd  !%+-1&26>7=OutliningState111$suQlOutliningState112$SvOutliningState113$~U8OutliningState114$gd'>B!DO#QW!Yd#fl5mr5sx$y},~-"DF":M! 2E',.,.@OutliningState80"ikidOutliningState78"gOutliningState77"dhfOutliningState82"fl{jR  C 2_benchmark.cpp *E+Jc:\stxxl\containers\bench_pqueue.cpp x ~=(:^1dd lkllude\stxxl\bits\containers\priority_queue.h{Bc:\stxxl\algo@DHOB B ABA B!%*&*+/+0459>:>2?B"E IR/0Tc:\stxxl\include\stxxl\bits\io\OutliningState73"FchOutliningState65"fOutliningState72"fNOutliningState74"jbwfs_file.hrre(ikTc:\stxxl\include\stxxl\bits\io\ufs_file.hNl3\c:\stxxl\include\stxxl\bits\io\syscall_file.hY"|\c:\stxxl\include\stxxl\bits\io\simdisk_file.hTv/Vc:\stxxl\include\stxxl\bits\io\OutliningState115$wyidOutliningState116$klOutliningState117$x|mlOutliningState118$ofmmap_file.h PA5236214}|stxhc:\stxxl\include\stxxl\bits\io\completion_handler.h3KAh||{ B359-4E41-9B60-3365922C`c:\stxxl\include\stxxl\bits\containers\vector.hf}^c:\stxxl\include\stxxl\bits\containers\stack.hd#OutliningState75"elZOutliningState76"lOutliningState81"NOutliningState79"}JOutliningState119${}qxOutliningState120$tpOutliningState121$zvnOutliningState122$xn^c:\stxxl\include\stxxl\bits\containers\queue.h9pc:\stxxl\include\stxxl\bits\containers\priority_queue.hW^c:\stxxl\include\stxxl\bits\containers\pager.h/Zc:\stxxl\include\stxxl\bits\containers\map.h,OutliningState123$zOutliningState124$|nOutliningState57"q~jOutliningState125$n^c:\stxxl\include\stxxl\bits\containers\deque.hӵ$dc:\stxxl\include\stxxl\bits\common\utils_ledasm.h@ &+'@CDGHI MNQRUVYZ[2`efgjOutliningState104$4OutliningState58"fOutliningState126$fOutliningState127$fkn1op8qy}~e,)+-/=  ""$9 *0$47*9<6=AFG5IN.PUW\-^a'c1gj1mqruVc:\stxxl\include\stxxl\bits\common\types.h:Vc:\stxxl\include\stxxl\bits\common\tuple.h4iVc:\stxxl\include\stxxl\bits\common\tmeta.h8Vc:\stxxl\include\stxxl\bits\common\timer.h><Xc:\stxxl\include\stxxl\bits\common\switch.hQVc:\stxxl\include\stxxl\bits\common\state.h+yfc:\stxxl\include\stxxl\bits\comOutliningState128$fOutliningState129$vhOutliningState130$fOutliningState59"Vvmon\simple_vector.hr!\c:\stxxl\include\stxxl\bits\common\settings.h)E^c:\stxxl\include\stxxl\bits\common\semaphore.huTc:\stxxl\include\stxxl\bits\common\seed.h 4 6OutliningState131$lOutliningState132$nOutliningState133$dOutliningState134$qOutliningState135$pOutliningState136$vOutliningState103$OutliningState137$d`c:\stxxl\include\stxxl\bits\common\exceptions.h*ưsion.h Tc:\stxxl\include\stxxl\bits\noncopyable.hPc:\stxxl\include\stxxl\bits\namespace.hR*OutliningState138$`OutliningState139$ OutliningState140$lOutliningState102$\c:\stxxl\include\stxxl\bits\compat_hash_set.hI= '' ,!"*#$-%((*~&1&: ;3=H?CHEJ%[ `"a f+g ux |L~&#Y" -..PPI! Pc:\stxxl\include\stxxl\bits\algo\sort.hWPc:\stxxl\include\stxxl\bits\algo\scan.hMsOutliningState141$`OutliningState142$`OutliningState143$lOutliningState56"t\c:\stxxl\include\stxxl\bits\algo\run_cursor.h ; dc:\stxxl\include\stxxl\bits\algo\random_shuffle.hZc:\stxxl\include\stxxl\bits\algo\losertree.hRc:\stxxl\include\stxxl\bits\algo\ksort.hSOutliningState144$jOutliningState145$bOutliningState146$hOutliningState147$jXc:\stxxl\include\stxxl\bits\algo\intksort.htZc:\stxxl\include\stxxl\bits\algo\inmemsort.h.ftc:\stxxl\include\stxxl\bits\mng\block_alloc_interleaved.hAWdc:\stxxl\include\stxxl\bits\algOutliningState148$OutliningState149$tOutliningState101$OutliningState100$o\async_schedule.hz&fc:\stxxl\algo\test_stable_ksort_all_parameters.cpp);!%'(),-026389;>A <C]G^?E`ez!{Hc:\stxxl\algo\test_stable_ksort.cppM!"#&'*,6-1 2KVc:\stxxl\algo\test_sort_all_parameters.cpp˜8c:\stxxl\algo\test_sort.cpp| "#OutliningState150$fOutliningState99"`OutliningState151$HOutliningState152$\$'(,/B0566:7;?7@DGJKN EQ Rn8c:\stxxl\algo\test_scan.cppT׏Lc:\stxxl\algo\test_random_shuffle.cppr#OutliningState153$TOutliningState154$TOutliningState98"&OutliningState155$hDc:\stxxl\algo\test_manyunits2.cppDc:\stxxl\algo\test_manyunits1.cpp D:c:\stxxl\algo\test_ksort.cpp "#'B(-42569:=.@6AE F|Xc:\stxxl\algo\test_ksort_all_parameters.cppD$8c:\stxxl\algo\test_asch.cpp^8c:\stxxl\algo\sort_file.cpp "#$'(+.6OutliningState156$HOutliningState97"`OutliningState157$FOutliningState96"L/3A69:=>A 4CBDIS W Jg6c:\stxxl\algo\gen_file.cpp2 &%;& *(+(-:.!0.1#3046     !"$%&'(*+,-./012345678;<=>?@ACDEFHIKLMNOQRSTUWXZ[]_adegilmnoqsu=?E("IJK@c:\stxxl\common\test_random.cppc: >c:\stxxl\common\stxxl_info.cppZ#%jc:\stxxl\containers\btree\test_corr_insert_erase.cppȉOutliningState158$POutliningState159$NOutliningState160$@OutliningState95"HOutliningState161$zOutliningState162$bOutliningState94" OutliningState93"Rc:\stxxl\containers\btree\test_btree.cppnLc:\stxxl\containers\write_vector2.cpp!%&-!.45DEIKLR!SwJc:\stxxl\containers\write_vector.cpp]g}$**+<=NOSUV\!]Zc:\stxxl\containers\tpie_stack_benchmark.cppB\KFcppk.cpp !(D).;/3;48:OutliningState163$jOutliningState164${VOutliningState165$OutliningState166$`OutliningState167$`OutliningState92"OutliningState168$k`OutliningState169$p9=:>CEFI JMDPQX[^Y^_d7h,04!WH6,D6OutliningState170$jOutliningState91"|OutliningState171$lOutliningState172$Z,D #35!d::c:\stxxl\io\flushbuffers.cppK,P[jlxk12(@!SOutliningState90"#NOutliningState89")OutliningState173$9@OutliningState88":0c:\stxxl\io\iostats.cpp;0j%(3)*+85:;=KLMNS/TUVabcdg#h&lo#p!msv$wxy&t|+0}5/)5/3/(3/C !"0c:\stxxl\io\sd_test.cpp:c:\stxxl\io\simdisk_file.cpp7z @#&KD$O P2&'!"2<<)=* .0'$C.DT)UZ/[k*l2%<=0c:\stxxl\io\test_io.cpp2.OutliningState174$GOutliningState87"JFOutliningState86"PpOutliningState175$V+#1$% ( :2c:\stxxl\io\unittest.cpp$%&+5,-$0'?C3DE3F@HKLN OW4c:\stxxl\mng\unittest.cpp1- $ #%&'456`avw( Bc:\stxxl\mng\test_write_pool.cppL޸  &Hc:\stxxl\mng\test_prefetch_pool.cppfx  (4c:\stxxl\mng\test_mng.cpp[Dc:\stxxl\mng\test_buf_streams.cpp@;OutliningState85"YOutliningState176$\DOutliningState177$I^TOutliningState178$`fVc:\stxxl\mng\test_block_alloc_strategy.cpp8c:\stxxl\utils\pq_param.cpp\7 F<c:\stxxl\utils\off_t_size.cppOutliningState84"jcOutliningState179$fLOutliningState180$hDOutliningState181$j@4c:\stxxl\utils\malloc.cpp<>Y0c:\stxxl\utils\log2.cpp&z`pN'*(+ -G14589< .>?@X!Y AfOutliningState182$pPOutliningState183$rZOutliningState184$tV@c:\stxxl\stream\test_stream.cpplKʅJc:\stxxl\stream\test_sorted_runs.cpp\ Fc:\stxxl\stream\test_push_sort.cpps\namespace.hre:\programme\microsoft visual studio 8\vc\inclu\stack.hyXc:\stxxl\include\stxxl\bits\common\switch.h0c:\stxxl\utils\log2.cppTc:\stxxl\include\stxxl\bits\common\seed.hjc:\stxxl\include\stxxl\bits\containers\btree\btree.h/4c:\stxxl\mng\write_pool.hVc:\stxxl\include\stxxl\bits\common\debug.hMxc:\stxxl\include\stxxl\bits\containers\btree\iterator_map.h0Pc:\stxxl\containers\test_migr_stack.cppJc:\stxxl\stream\test_sorted_runs.cpp8c:\stxxl\common\version.cpp`:c:\stxxl\io\syscall_file.cppD0c:\stxxl\common\utils.hZc:\stxxl\incluy_stacks.cpp|c:\Program Files\Microsoft Visual Studio 8\VC\include\utility7`c:\stxxl\containers\leda_sm_stack_benchmark.cpp8c:\stxxl\algo\test_scan.cppVc:\stxxl\include\stxxl\bits\common\state.h&c:\stxxl\mng\mng.h*c:\stxxl\io\iobase.h4c:\stxxl\containers\map.h!dc:\stxxl\include\stxxl\bits\common\utils_ledasm.hh>c:\stxxl\utils\createdisks.cppHFc:\stxxl\containers\test_deque.cppHc:\stxxl\containers\test_vector.cpp&@c:\stxxl\io\benchmark_disks.cppI6c:\stxxl\algo\gen_file.cpp8c:\stxxl\algo\sort_file.cppaNc:\stxxl\containers\btree\node_cache.h Hc:\stxxl\include\stxxl\bits\io\io.h@Pc:\stxxl\containers\map_test_handlers.hPc:\stxxl\containers\stack_benchmark.cpp8c:\stxxl\containers\deque.hVc:\stxxl\include\stxxl\bits\common\utils.h>fc:\stxxl\include\stxxl\bits\common\simple_vector.h;\c:\stxxl\include\stxxl\bits\io\boostfd_file.hEJc:\stxxl\containers\bench_pqueue.cppJc:\stxxl\containers\pq_benchmark.cpp\4c:\stxxl\io\mmap_file.cpp)Rc:\stxxl\include\stxxl\bits\algo\ksort.hLc:\stxxl\include\stxxl\bits\version.hg\c:\stxxl\include\stxxl\bits\compat_hash_map.hLtc:\stxxl\include\stxxl\bits\containers\btree\node_cache.h+4c:\stxxl\mng\test_mng.cpp`c:\stxxl\include\stxxl\bits\mng\prefetch_pool.hlRc:\stxxl\include\stxxl\bits\io\iostats.h<6c:\stxxl\io\syscall_file.h(*c:\stxxl\mng\mng.cppfc:\stxxl\include\stxxl\bits\common\aligned_alloc.h@c:\stxxl\common\simple_vector.h%6c:\stxxl\mng\test_mng1.cppLc:\stxxl\include\stxxl\bits\mng\mng.h4Vc:\stxxl\include\stxxl\bits\common\types.h:Zc:\stxxl\containers\tpie_stack_benchmark.cppDc:\stxxl\algo\test_manyunits2.cppPc:\stxxl\include\stxxl\bits\io\iobase.h2~c:\Program Files\Microsoft Visual Studio 8\VC\include\assert.h3Xc:\stxxl\include\st xxl\bits\stream\stream.hj:c:\stxxl\containers\vector.h#te:\programme\microsoft visual studio 8\vc\include\xmemory\c:\stxxl\containers\berkeley_db_benchmark.cpp\c:\stxxl\include\stxxl\bits\compat_auto_ptr.hNc:\stxxl\containers\test_iterators.cppVc:\stxxl\include\stxxl\bits\io\mmap_file.hv:c:\stxxl\io\simdisk_file.cppXBc:\stxxl\containers\btree\leaf.h ^c:\stxxl\include\stxxl\bits\common\semaphore.h0c:\stxxl\algo\adaptor.h'Xc:\stxxl\algo\test_ksort_all_parameters.cpphc:\stxxl\include\stxxl\bits\io\completion_handler.hw8c:\stxxl\utils\pq_param.cppT2c:\stxxl\common\rand.cppBJc:\stxxl\containers\monotonic_pq.cppK:c:\stxxl\algo\test_ksort.cppbhc:\stxxl\include\stxxl\bits\containers\btree\node.h*te:\programme\microsoft visual studio 8\vc\include\xstring\c:\stxxl\include\stxxl\bits\io\simdisk_file.huVc:\stxxl\algo\test_sort_all_parameters.cppPc:\stxxl\include\stxxl\bits\algo\sort.hvE:\Programme\Microsoft Visual Studio 8\VC\include\xutilityPc:\stxxl\containers\test_ext_merger.cppbc:\stxxl\include\stxxl\bits\stream\sort_stream.hk0c:\stxxl\io\iostats.cppY\c:\stxxl\include\stxxl\bits\algo\run_cursor.hhc:\stxxl\include\stxxl\bits\containers\btree\leaf.h18c:\stxxl\algo\test_asch.cppDc:\stxxl\containers\copy_file.cpp[:c:\stxxl\io\wincall_file.cppOfc:\stxxl\algo\test_stable_ksort_all_parameters.cppe"c:\stxxl\io\io.hPc:\stxxl\containers\btree\btree_pager.hRc:\stxxl\containers\test_ext_merger2.cppJ4c:\stxxl\utils\malloc.cppZc:\stxxl\include\stxxl\bits\algo\losertree.h^c:\stxxl\include\stxxl\bits\containers\pager.h|ne:\programme\microsoft visual studio 8\vc\include\list 8c:\stxxl\algo\test_sort.cppc2c:\stxxl\io\ufs_file.cppQ4c:\stxxl\io\diskqueue.cppGTc:\stxxl\include\stxxl\bits\common\rand.hPPc:\stxxl\include\stxxl\bits\algo\scan.hTc:\stxxl\include\stxxl\bits\io\wfs_file.hrVc:\stxxl\include\stxxl\bits\common\mutex.hFDc:\stxxl\containers\btree\btree.h Zc:\stxxl\containers\leda_sm_pq_benchmark.cppFc:\stxxl\containers\test_stack.cpppc:\stxxl\include\stxxl\bits\containers\btree\iterator.h-Zc:\stxxl\include\stxxl\bits\algo\inmemsort.hHc:\stxxl\containers\test_pqueue.cppstxxl-1.3.1/TROUBLESHOOTING0000644000175000017500000000031411323316604014721 0ustar andreasandreasSee the TROUBLESHOOTING section in the make.settings file. If your problem is not solved, please leave a message in the forums at http://sourceforge.net/projects/stxxl/forums Your input is very welcome! stxxl-1.3.1/common/0000755000175000017500000000000011536252421014003 5ustar andreasandreasstxxl-1.3.1/common/test_random.cpp0000644000175000017500000000346511531237734017043 0ustar andreasandreas/*************************************************************************** * common/test_random.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright © 2007, 2008 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #include #include #include int main() { //stxxl::set_seed(42); std::cout << "seed = " << stxxl::get_next_seed() << std::endl; stxxl::srandom_number32(stxxl::get_next_seed()); #ifndef BOOST_MSVC srand48(time(NULL)); #endif stxxl::random_number32 random_number32; stxxl::random_number32_r random_number32_r; stxxl::random_uniform_fast random_uniform_fast; stxxl::random_uniform_slow random_uniform_slow; stxxl::random_number<> random_number_fast; stxxl::random_number random_number_slow; stxxl::random_number64 random_number64; for (int i = 0; i < 3; ++i) { #ifndef BOOST_MSVC std::cout << "d48 " << drand48() << std::endl; #endif std::cout << "r32 " << random_number32() << std::endl; std::cout << "r3r " << random_number32_r() << std::endl; std::cout << "ruf " << random_uniform_fast() << std::endl; std::cout << "rus " << random_uniform_slow() << std::endl; std::cout << "rnf " << random_number_fast(42) << std::endl; std::cout << "rns " << random_number_slow(42) << std::endl; std::cout << "r64 " << random_number64() << std::endl; std::cout << std::endl; } stxxl::set_seed(42); assert(stxxl::get_next_seed() == 42); assert(stxxl::get_next_seed() != 42); } stxxl-1.3.1/common/seed.cpp0000644000175000017500000000333011531237734015433 0ustar andreasandreas/*************************************************************************** * common/seed.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2007, 2008 Andreas Beckmann * Copyright (C) 2008 Roman Dementiev * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #include #include #ifdef STXXL_BOOST_CONFIG #include #endif #ifdef BOOST_MSVC #include #include #else #include #include #endif #include #include __STXXL_BEGIN_NAMESPACE inline unsigned initial_seed(); struct seed_generator_t { unsigned seed; mutex mtx; seed_generator_t(unsigned s) : seed(s) { } }; seed_generator_t & seed_generator() { static seed_generator_t sg(initial_seed()); return sg; } inline unsigned initial_seed() { static bool initialized = false; assert(!initialized); // this should only be called once! initialized = true; #ifdef BOOST_MSVC // GetTickCount(): ms since system start return GetTickCount() ^ GetCurrentProcessId(); #else struct timeval tv; gettimeofday(&tv, 0); return tv.tv_sec ^ tv.tv_usec ^ (getpid() << 16); #endif } void set_seed(unsigned seed) { scoped_mutex_lock Lock(seed_generator().mtx); seed_generator().seed = seed; } unsigned get_next_seed() { scoped_mutex_lock Lock(seed_generator().mtx); return seed_generator().seed++; } __STXXL_END_NAMESPACE stxxl-1.3.1/common/log.cpp0000644000175000017500000000247211535151017015273 0ustar andreasandreas/*************************************************************************** * common/log.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2004-2005 Roman Dementiev * Copyright (C) 2008 Johannes Singler * Copyright (C) 2009 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #include __STXXL_BEGIN_NAMESPACE logger::logger() : waitlog_stream_(NULL) { const char * log_filename = getenv("STXXLLOGFILE"); log_stream_.open(log_filename == NULL ? "stxxl.log" : log_filename); const char * errlog_filename = getenv("STXXLERRLOGFILE"); errlog_stream_.open(errlog_filename == NULL ? "stxxl.errlog" : errlog_filename); #ifdef STXXL_WAIT_LOG_ENABLED const char * waitlog_filename = getenv("STXXLWAITLOGFILE"); if (waitlog_filename) { waitlog_stream_ = new std::ofstream(waitlog_filename); *waitlog_stream_ << "# time\trd_incr\twr_incr\tw_read\tw_write" << std::endl; } #endif } logger::~logger() { delete waitlog_stream_; } __STXXL_END_NAMESPACE stxxl-1.3.1/common/test_globals.cpp0000644000175000017500000000106711520262313017167 0ustar andreasandreas/*************************************************************************** * common/test_globals.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2011 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #include stxxl::vector global_vector; int main() { return 0; } stxxl-1.3.1/common/Makefile.common0000644000175000017500000000026411514126051016727 0ustar andreasandreasTESTS = test_random test_manyunits test_globals TESTS_NON_MSVC = LIB_SRC = rand.cpp seed.cpp version.cpp exithandler.cpp verbose.cpp log.cpp UTIL_BINARIES = stxxl_info stxxl-1.3.1/common/rand.cpp0000644000175000017500000000121711026753412015434 0ustar andreasandreas/*************************************************************************** * common/rand.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2002 Roman Dementiev * Copyright (C) 2007 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #include __STXXL_BEGIN_NAMESPACE unsigned ran32State = get_next_seed(); __STXXL_END_NAMESPACE stxxl-1.3.1/common/verbose.cpp0000644000175000017500000000443311513611117016154 0ustar andreasandreas/*************************************************************************** * common/verbose.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2009, 2010 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #include #include #include #include #include #include #include #ifndef STXXL_THREAD_ID # ifdef BOOST_MSVC # define STXXL_THREAD_ID (-1) # else # define STXXL_THREAD_ID pthread_self() # endif #endif __STXXL_BEGIN_NAMESPACE static const double program_start_time_stamp = timestamp(); void print_msg(const char * label, const std::string & msg, unsigned flags) { std::string s; #ifdef STXXL_PRINT_TIMESTAMP_ALWAYS const bool timestamp_always = true; #else const bool timestamp_always = false; #endif if (timestamp_always || (flags & _STXXL_PRNT_TIMESTAMP)) { double t = timestamp() - program_start_time_stamp; char tstr[23]; /* "[364:23:59:59.999999] " */ snprintf(tstr, sizeof(tstr), "[%d.%02d:%02d:%02d.%06d] ", int(t / (24 * 60 * 60)), int(t / (60 * 60)) % 24, int(t / 60) % 60, int(t) % 60, int((t - floor(t)) * 1000000)); s += tstr; } if (label) { s += '['; s += label; s += "] "; } if (flags & _STXXL_PRNT_THREAD_ID) { char tstr[32]; snprintf(tstr, sizeof(tstr), "[T%ld] ", long(STXXL_THREAD_ID)); s += tstr; } s += msg; if (flags & _STXXL_PRNT_ADDNEWLINE) s += '\n'; if (flags & _STXXL_PRNT_COUT) std::cout << s << std::flush; if (flags & _STXXL_PRNT_CERR) std::cerr << s << std::flush; logger * logger_instance = logger::get_instance(); if (flags & _STXXL_PRNT_LOG) logger_instance->log_stream() << s << std::flush; if (flags & _STXXL_PRNT_ERRLOG) logger_instance->errlog_stream() << s << std::flush; } __STXXL_END_NAMESPACE // vim: et:ts=4:sw=4 stxxl-1.3.1/common/version.cpp0000644000175000017500000000400711531237734016202 0ustar andreasandreas/*************************************************************************** * common/version.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2007, 2008 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #include #ifdef STXXL_BOOST_CONFIG #include #endif #define STXXL_VERSION_STRING_MA_MI_PL "1.3.1" // version.defs gets created if a snapshot/beta/rc/release is done #ifdef HAVE_VERSION_DEFS #include "version.defs" #endif // version_svn.defs gets created if stxxl is built from SVN #ifdef HAVE_VERSION_SVN_DEFS #include "version_svn.defs" #endif __STXXL_BEGIN_NAMESPACE // FIXME: this currently only works for GNU-like systems, // there are no details available on windows platform const char * get_version_string() { return "STXXL" #ifdef STXXL_VERSION_STRING_SVN_BRANCH " (branch: " STXXL_VERSION_STRING_SVN_BRANCH ")" #endif " v" STXXL_VERSION_STRING_MA_MI_PL #ifdef STXXL_VERSION_STRING_DATE "-" STXXL_VERSION_STRING_DATE #endif #ifdef STXXL_VERSION_STRING_SVN_REVISION " (SVN r" STXXL_VERSION_STRING_SVN_REVISION ")" #endif #ifdef STXXL_VERSION_STRING_PHASE " (" STXXL_VERSION_STRING_PHASE ")" #else " (prerelease)" #endif #ifdef STXXL_VERSION_STRING_COMMENT " (" STXXL_VERSION_STRING_COMMENT ")" #endif #ifdef __MCSTL__ " + MCSTL" #ifdef MCSTL_VERSION_STRING_DATE " " MCSTL_VERSION_STRING_DATE #endif #ifdef MCSTL_VERSION_STRING_SVN_REVISION " (SVN r" MCSTL_VERSION_STRING_SVN_REVISION ")" #endif #endif #ifdef STXXL_BOOST_CONFIG " + Boost " #define Y(x) # x #define X(x) Y(x) X(BOOST_VERSION) #undef X #undef Y #endif ; } __STXXL_END_NAMESPACE // vim: et:ts=4:sw=4 stxxl-1.3.1/common/GNUmakefile0000644000175000017500000000105111346235727016063 0ustar andreasandreasTOPDIR ?= .. include Makefile.common TESTS-yes += $(TESTS_NON_MSVC) include $(TOPDIR)/Makefile.subdir.gnu tools: $(UTIL_BINARIES:=.$(bin)) clean:: $(RM) $(UTIL_BINARIES:=.$(bin)) obj-test_manyunits = test_manyunits.$o test_manyunits2.$o test_manyunits.$(bin): $(obj-test_manyunits) $(STXXL_LIBDEPS) $(call LINK_STXXL, $(obj-test_manyunits)) ifneq (,$(wildcard .svn)) version.$(lo): STXXL_COMPILER_OPTIONS += -DHAVE_VERSION_SVN_DEFS endif ifneq (,$(wildcard version.defs)) version.$(lo): STXXL_COMPILER_OPTIONS += -DHAVE_VERSION_DEFS endif stxxl-1.3.1/common/test_manyunits.cpp0000644000175000017500000000075511270272020017574 0ustar andreasandreas/*************************************************************************** * common/test_manyunits.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2004 Roman Dementiev * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #include stxxl-1.3.1/common/exithandler.cpp0000644000175000017500000000331411271540171017015 0ustar andreasandreas/*************************************************************************** * common/exithandler.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2009 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #include // 1. do nothing for default handler // 2. #define STXXL_NON_DEFAULT_EXIT_HANDLER for a handler that does not use atexit() // 3. #define STXXL_EXTERNAL_EXIT_HANDLER to provide your own implementation #ifndef STXXL_EXTERNAL_EXIT_HANDLER #ifndef STXXL_NON_DEFAULT_EXIT_HANDLER #include __STXXL_BEGIN_NAMESPACE // default exit handler int register_exit_handler(void (* function)(void)) { return atexit(function); } // default exit handler void run_exit_handlers() { // nothing to do } __STXXL_END_NAMESPACE #else // STXXL_NON_DEFAULT_EXIT_HANDLER #include #include __STXXL_BEGIN_NAMESPACE mutex exit_handler_mutex; std::vector exit_handlers; int register_exit_handler(void (* function)(void)) { scoped_mutex_lock lock(exit_handler_mutex); exit_handlers.push_back(function); return 0; } // default exit handler void run_exit_handlers() { scoped_mutex_lock lock(exit_handler_mutex); while (!exit_handlers.empty()) { (*(exit_handlers.back()))(); exit_handlers.pop_back(); } } __STXXL_END_NAMESPACE #endif // STXXL_NON_DEFAULT_EXIT_HANDLER #endif // STXXL_EXTERNAL_EXIT_HANDLER // vim: et:ts=4:sw=4 stxxl-1.3.1/common/test_manyunits2.cpp0000644000175000017500000000101411270272020017643 0ustar andreasandreas/*************************************************************************** * common/test_manyunits2.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2004 Roman Dementiev * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #include int main() { return 0; } stxxl-1.3.1/common/Makefile0000644000175000017500000000356611514126051015450 0ustar andreasandreasinclude Makefile.common include ../make.settings tools: $(UTIL_BINARIES) tests: $(TESTS) #tests: $(TESTS_NON_MSVC) lib: rand.$(OBJEXT) version.$(OBJEXT) seed.$(OBJEXT) exithandler.$(OBJEXT) verbose.$(OBJEXT) log.$(OBJEXT) rand.$(OBJEXT): rand.cpp $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c rand.cpp version.$(OBJEXT): version.cpp $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c version.cpp seed.$(OBJEXT): seed.cpp $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c seed.cpp exithandler.$(OBJEXT): exithandler.cpp $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c exithandler.cpp verbose.$(OBJEXT): verbose.cpp $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c verbose.cpp log.$(OBJEXT): log.cpp $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c log.cpp DEPENDENCIES = $(COMMON_FILES) $(IO_LAYER_FILES) $(MNG_LAYER_FILES) $(CONTAINER_FILES) $(ALGO_FILES) stxxl_info: stxxl_info.$(EXEEXT) stxxl_info.$(EXEEXT): stxxl_info.cpp $(DEPENDENCIES) $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c stxxl_info.cpp $(LINKER) stxxl_info.$(OBJEXT) $(OUT)stxxl_info.$(EXEEXT) $(STXXL_LINKER_OPTIONS) test_random: test_random.$(EXEEXT) test_random.$(EXEEXT): test_random.cpp $(DEPENDENCIES) $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c test_random.cpp $(LINKER) test_random.$(OBJEXT) $(OUT)test_random.$(EXEEXT) $(STXXL_LINKER_OPTIONS) test_manyunits: test_manyunits.$(EXEEXT) test_manyunits.$(EXEEXT): test_manyunits.cpp test_manyunits2.cpp $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c test_manyunits.cpp $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c test_manyunits2.cpp $(LINKER) test_manyunits.$(OBJEXT) test_manyunits2.$(OBJEXT) $(OUT)test_manyunits.$(EXEEXT) $(STXXL_LINKER_OPTIONS) test_globals: test_globals.$(EXEEXT) test_globals.$(EXEEXT): test_globals.cpp $(DEPENDENCIES) $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c test_globals.cpp $(LINKER) test_globals.$(OBJEXT) $(OUT)test_globals.$(EXEEXT) $(STXXL_LINKER_OPTIONS) clean: $(RM) $(CLEAN_TARGETS) stxxl-1.3.1/common/stxxl_info.cpp0000644000175000017500000000355211535152472016715 0ustar andreasandreas/*************************************************************************** * common/stxxl_info.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright © 2007, 2009-2011 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #include #include #include int main(int argc, char **) { stxxl::config::get_instance(); stxxl::block_manager::get_instance(); stxxl::stats::get_instance(); stxxl::disk_queues::get_instance(); #ifdef STXXL_PARALLEL_MODE #ifdef _GLIBCXX_PARALLEL STXXL_MSG("_GLIBCXX_PARALLEL, max threads = " << omp_get_max_threads()); #else STXXL_MSG("STXXL_PARALLEL_MODE, max threads = " << omp_get_max_threads()); #endif #elif defined(__MCSTL__) STXXL_MSG("__MCSTL__, max threads = " << omp_get_max_threads()); #endif STXXL_MSG("sizeof(unsigned int) = " << sizeof(unsigned int)); STXXL_MSG("sizeof(unsigned_type) = " << sizeof(stxxl::unsigned_type)); STXXL_MSG("sizeof(uint64) = " << sizeof(stxxl::uint64)); STXXL_MSG("sizeof(size_t) = " << sizeof(size_t)); STXXL_MSG("sizeof(off_t) = " << sizeof(off_t)); STXXL_MSG("sizeof(void*) = " << sizeof(void *)); #if defined(STXXL_HAVE_AIO_FILE) STXXL_MSG("STXXL_HAVE_AIO_FILE = " << STXXL_HAVE_AIO_FILE); #endif STXXL_MSG("STXXL_HAVE_SHARED_PTR = " << STXXL_HAVE_SHARED_PTR); STXXL_MSG("STXXL_HAVE_MAKE_SHARED = " << STXXL_HAVE_MAKE_SHARED); assert(argc < 3); // give two extra arguments to check whether assertions are enabled return argc != 2 ? 0 : -1; // give one extra argument to get exit code -1 } stxxl-1.3.1/common/version.defs0000644000175000017500000000005511536252421016333 0ustar andreasandreas#define STXXL_VERSION_STRING_PHASE "release" stxxl-1.3.1/misc/0000755000175000017500000000000011536252421013446 5ustar andreasandreasstxxl-1.3.1/misc/concat-lines0000755000175000017500000000154111513611117015750 0ustar andreasandreas#!/usr/bin/perl ############################################################################ # misc/concat-lines # # Part of the STXXL. See http://stxxl.sourceforge.net # # Copyright (C) 2007 Johannes Singler # Copyright (C) 2010 Andreas Beckmann # # Distributed under the Boost Software License, Version 1.0. # (See accompanying file LICENSE_1_0.txt or copy at # http://www.boost.org/LICENSE_1_0.txt) ############################################################################ # Concatenate the lines of file $ARGV[0] which both satisfy regular expression $ARGV[1] $regex = $ARGV[0]; shift; $former = ''; while($line = <>) { if(!($line =~ /$regex/) || !($former =~ /$regex/)) { print("\n"); } else { print("\t"); } chomp($line); print($line); $former = $line; } print("\n"); stxxl-1.3.1/misc/libgomp.supp0000644000175000017500000000102411254677564016025 0ustar andreasandreas{ libgomp/gomp_new_team/malloc Memcheck:Leak fun:malloc fun:gomp_malloc fun:gomp_new_team fun:GOMP_parallel_start } { libgomp/gomp_team_start/malloc Memcheck:Leak fun:malloc fun:gomp_malloc fun:gomp_team_start } { libgomp/gomp_team_start/realloc Memcheck:Leak fun:malloc fun:realloc fun:gomp_realloc fun:gomp_team_start } { libgomp/gomp_team_start/pthread_create Memcheck:Leak fun:calloc fun:_dl_allocate_tls fun:pthread_create@@GLIBC_2.2.5 fun:gomp_team_start } stxxl-1.3.1/misc/fix-properties0000755000175000017500000000222111535455344016361 0ustar andreasandreas#!/bin/sh svn ps svn:eol-style native [A-Z]*[A-Z] find misc -name .svn -prune -o -type f -exec svn ps svn:eol-style native {} \; find . -name .svn -prune -o \( -type f -a \( \ -name "*.h" \ -o -name "*.cpp" \ -o -name "Makefile*" \ -o -name "GNUmakefile*" \ -o -name "*.tex" \ -o -name "*.bib" \ -o -name "*.fig" \ -o -name "*.svg" \ -o -name "*html" \ -o -name "*.css" \ \) -exec svn ps svn:eol-style native {} \; \) find include -name .svn -prune -o \( -type f \ -exec svn ps svn:eol-style native {} \; \) find . -name .svn -prune -o \( -type f -a \( \ -name "*.gif" \ \) -exec svn ps svn:mime-type image/gif {} \; \) find . -name .svn -prune -o \( -type f -a \( \ -name "*.jpg" -o -name "*.jpeg" \ \) -exec svn ps svn:mime-type image/jpeg {} \; \) find . -name .svn -prune -o \( -type f -a \( \ -name "*.png" \ \) -exec svn ps svn:mime-type image/png {} \; \) find . -name .svn -prune -o \( -type f -a \( \ -name "*.pdf" \ \) -exec svn ps svn:mime-type application/pdf {} \; \) find . -name .svn -prune -o \( -type f -a \( \ -name "*.ps" -o -name "*.eps" \ \) -exec svn ps svn:mime-type application/postscript {} \; \) stxxl-1.3.1/misc/uncrustify.mk0000644000175000017500000000521311535457411016220 0ustar andreasandreas############################################################################ # misc/uncrustify.cfg # misc/uncrustify.mk # # Part of the STXXL. See http://stxxl.sourceforge.net # # Copyright (C) 2007-2008 Andreas Beckmann # # Distributed under the Boost Software License, Version 1.0. # (See accompanying file LICENSE_1_0.txt or copy at # http://www.boost.org/LICENSE_1_0.txt) ############################################################################ SUBDIRS += . SUBDIRS += include include/stxxl include/stxxl/bits SUBDIRS += $(foreach d, algo common compat containers containers/btree io mng stream utils, include/stxxl/bits/$d) SUBDIRS += algo common containers containers/btree io mng stream utils contrib SUBDIRS += doc/tutorial/examples FILES_IGNORE := ./doxymain.h FILES := $(filter-out $(FILES_IGNORE),$(wildcard $(foreach d, $(SUBDIRS), $d/*.h $d/*.cpp))) FILES += $(filter-out include/stxxl/bits %.uncrustify %.diff,$(wildcard include/stxxl/*)) all: uncrustify-test all: uncrustify-diff uncrustify-test: $(FILES:=.uncrustify) uncrustify-diff: $(FILES:=.diff) uncrustify-apply: $(FILES:=.unc-apply) viewdiff: view $(wildcard $(foreach d, $(SUBDIRS), $d/*.diff)) clean: $(RM) $(FILES:=.uncrustify) $(FILES:=.uncrustifyT) $(FILES:=.diff) $(RM) $(UNCRUSTIFY_CFG)-file-header .SECONDARY: ############################################################################ #UNCRUSTIFY ?= ./uncrustify UNCRUSTIFY ?= uncrustify UNCRUSTIFY_CFG ?= misc/uncrustify.cfg UNCRUSTIFY_FLAGS+= -c $(UNCRUSTIFY_CFG) -l CPP %.diff: % %.uncrustify @test -f $* @test -f $*.uncrustify diff -u $^ > $@ || test $$? = 1 test -s $@ || $(RM) $@ %.uncrustify: % $(UNCRUSTIFY_CFG) #$(UNCRUSTIFY) $(RM) $<.diff $(UNCRUSTIFY) $(UNCRUSTIFY_FLAGS) -o $@T < $< sed -i -e 's/ *$$//' $@T mv $@T $@ %.unc-apply: %.uncrustify cmp -s $* $*.uncrustify || cp $*.uncrustify $* update-uncrustify-cfg: $(UNCRUSTIFY) -c $(UNCRUSTIFY_CFG) --update-config-with-doc | \ sed -e '/indent_access_spec/s/-[0-9][0-9]*/-indent_columns/' > $(UNCRUSTIFY_CFG).tmp cmp -s $(UNCRUSTIFY_CFG).tmp $(UNCRUSTIFY_CFG) || cp -p $(UNCRUSTIFY_CFG) $(UNCRUSTIFY_CFG).old cmp -s $(UNCRUSTIFY_CFG).tmp $(UNCRUSTIFY_CFG) || cp $(UNCRUSTIFY_CFG).tmp $(UNCRUSTIFY_CFG) $(RM) $(UNCRUSTIFY_CFG).tmp uncrustify-file-header: $(UNCRUSTIFY_CFG)-file-header $(MAKE) -f $(lastword $(MAKEFILE_LIST)) uncrustify-test uncrustify-diff UNCRUSTIFY_CFG=$(UNCRUSTIFY_CFG)-file-header $(UNCRUSTIFY_CFG)-file-header: $(UNCRUSTIFY_CFG) sed -e '/cmt_insert_file_header/s/""/misc\/fileheader.txt/' $< > $@ .PHONY: all clean viewdiff uncrustify-test uncrustify-diff uncrustify-apply update-uncrustify-cfg stxxl-1.3.1/misc/analyze-include-dependencies.pl0000755000175000017500000001527211312125725021523 0ustar andreasandreas#!/usr/bin/perl -w # # A tool to analyze #include dependencies and find unwanted cycles. # # Copyright (C) 2007-2008 Andreas Beckmann # # Distributed under the Boost Software License, Version 1.0. # (See accompanying file LICENSE_1_0.txt or copy at # http://www.boost.org/LICENSE_1_0.txt) # use File::Basename; $debug = 0; $fakeheaders = 'fakeinclude'; # fake headers currently needed to prevent canonical name errors: # backward_warning.h -> backward/backward_warning.h # io.h -> #nothing # platform.hpp -> boost/thread/detail/platform.hpp # thread_data.hpp -> boost/thread/pthread/thread_data.hpp # thread_heap_alloc.hpp -> boost/thread/detail/thread_heap_alloc.hpp # vstring.tcc -> ext/vstring.tcc $mcstl = 0; $mcstlpath = 'c++'; $stxxl = 1; $stxxlpath = 'include'; #$CXX = 'g++-4.2'; $CXX = 'g++-4.4 -std=c++0x'; $cxxtarget = 'foo-bar-gnu'; $cxxheaderpath = undef; $gcctargetheaderpath = undef; @includepath = (); push @includepath, $fakeheaders if $fakeheaders; push @includepath, $mcstlpath if $mcstl; push @includepath, $stxxlpath if $stxxl; %breakloops = qw( libio.h _G_config.h sys/cdefs.h features.h sys/ucontext.h signal.h debug/formatter.h debug/debug.h debug/bitset bitset debug/deque deque debug/list list debug/map map debug/set set debug/vector vector bits/sstream.tcc sstream debug/hash_map ext/hash_map debug/hash_set ext/hash_set debug/unordered_map unordered_map debug/unordered_set unordered_set xmmintrin.h emmintrin.h ext/vstring.h vstring.tcc wctype.h wchar.h stdatomic.h cstdatomic algorithm parallel/algorithm numeric parallel/numeric bits/stl_algobase.h parallel/algobase.h parallel/partition.h parallel/sort.h boost/type_traits/is_class.hpp boost/type_traits/is_scalar.hpp boost/type_traits/msvc/remove_cv.hpp boost/type_traits/is_pointer.hpp boost/preprocessor/list/fold_left.hpp boost/preprocessor/control/while.hpp boost/preprocessor/list/fold_right.hpp boost/preprocessor/control/while.hpp ); %seen = (); @todo = (); %in = (); %out = (); $out{'MISSING'} = []; %canonical = (); sub get_file_list($;@) { my $path = shift; my @patterns = @_; @patterns = ('*') unless scalar @patterns; my @l; foreach my $p (@patterns){ foreach (glob "$path/$p") { if (-f $_) { my $x = $path; $x =~ s/([+])/\\$1/g; s|^$x/||; push @l, $_; } } } print "GLOB $path @patterns: @l\n" if $debug; return @l; } sub get_cxx_include_paths($) { my $cxx = shift; open CXXOUT, "$cxx -E -v -xc++ /dev/null 2>&1 >/dev/null |" or die $!; my $ok = 0; while () { chomp; $cxxtarget = $1 if /^Target: (.*)/; $ok = 1 if /^#include .\.\.\.. search starts here:$/; $ok = 0 if /^End of search list\.$/; if ($ok && s/^ //) { next if /backward/; push @includepath, $_; unless ($cxxheaderpath) { $cxxheaderpath = $_ if m|/c\+\+|; } unless ($gcctargetheaderpath) { $gcctargetheaderpath = $_ if (m|/$cxxtarget/| && ! m|/c\+\+|); } } } close CXXOUT; print "TARGET: \t$cxxtarget\n"; print "HEADERS c++: \t$cxxheaderpath\n"; print "HEADERS gcc: \t$gcctargetheaderpath\n"; print "INCLUDES: \t@includepath\n"; } sub find_header($;$) { my $header = shift; my $relpath = dirname(shift || '.'); foreach $_ (@includepath, $relpath) { my $file = "$_/$header"; if (-f $file) { if (exists $canonical{$file} && $canonical{$file} ne $header) { print "CANONICAL MISMATCH: $file $header $canonical{$file}\n"; } $canonical{$file} = $header; print "FOUND: $header as $file\n" if $debug; return [ $header, "$file" ]; } } print "NOT FOUND: $header\n"; return [$header, undef]; } sub parse_header($) { my $arg = shift; my $header = $$arg[0]; my $file = $$arg[1]; return if $seen{$file || $header}; $seen{$file || $header} = 1; if ($file) { print "PROCESSING: $header \t($file)\n"; print "OUCH: $header\n" if exists $$out{$header}; $out{$header} = []; open HEADER,"<$file" or die $!; while ($_ =

) { if (/^\s*#\s*include\s*["<]([^">]*)[">]/) { my $dep_header = $1; print "DEP: $header \t$dep_header\n"; push @{$out{$header}}, $dep_header; push @{$in{$dep_header}}, $header; push @todo, find_header($dep_header, $file); } } close HEADER; } else { print "NOT FOUND: $header\n"; push @{$out{$header}}, 'MISSING'; push @{$in{'MISSING'}}, $header; } } get_cxx_include_paths($CXX); @cxxheaders = get_file_list($cxxheaderpath); #@cxxbwheaders = get_file_list("$cxxheaderpath/backward"); push @cxxbwheaders, get_file_list($cxxheaderpath, "backward/*"); @cxxextheaders = get_file_list($cxxheaderpath, 'ext/*'); @cxxbitsheaders = get_file_list($cxxheaderpath, 'bits/*'); @cxxtargetheaders = get_file_list("$cxxheaderpath/$cxxtarget", '*', 'bits/*'); #@cxxtr1headers = get_file_list($cxxheaderpath, 'tr1/*', 'tr1_impl/*'); @gcctargetheaders = get_file_list($gcctargetheaderpath, '*.h', 'bits/*.h'); if ($mcstl) { @mcstlheaders = get_file_list($mcstlpath); @mcstlmetaheaders = get_file_list($mcstlpath, 'meta/*'); @mcstlbitsheaders = get_file_list($mcstlpath, 'bits/*'); push @todo, find_header($_) foreach ( sort(@mcstlheaders), sort(@mcstlmetaheaders), sort(@mcstlbitsheaders), ); } if ($stxxl) { @stxxlheaders = get_file_list($stxxlpath, '*', 'stxxl/*'); @stxxlbitsheaders = get_file_list($stxxlpath, 'bits/*', 'stxxl/bits/*', 'stxxl/bits/*/*'); push @todo, find_header($_) foreach ( sort(@stxxlheaders), sort(@stxxlbitsheaders), ); } push @todo, find_header($_) foreach ( sort(@cxxheaders), sort(@cxxbwheaders), sort(@cxxextheaders), sort(@cxxbitsheaders), sort(@cxxtargetheaders), #sort(@cxxtr1headers), sort(@gcctargetheaders), ); while (@todo) { parse_header(shift @todo); } %odgr = (); @zodgr = (); if ($debug) { foreach (sort keys %out) { print "\t$_\n\t=> (".(scalar @{$out{$_}}).")\t"; foreach (@{$out{$_}}) { print " $_"; } print "\n\t<= (".(scalar @{$in{$_}}).")\t"; foreach (@{$in{$_}}) { print " $_"; } print "\n"; } } foreach (sort keys %out) { $odgr{$_} = scalar @{$out{$_}}; push @zodgr, $_ if $odgr{$_} == 0; } while (my ($h, $l) = each %breakloops) { next unless exists $out{$h}; foreach (@{$out{$h}}) { if ($l eq $_) { print "BREAK LOOP: $h --> $l\n"; --$odgr{$h}; push @zodgr, $h if $odgr{$h} == 0; $_ .= ".UNLOOP"; } } foreach (@{$in{$l}}) { if ($h eq $_) { $_ .= ".UNLOOP"; } } } print "TOPSORT:\n"; while (@zodgr) { $curr = shift @zodgr; next unless exists $out{$curr}; print "\t$curr"; foreach (@{$in{$curr}}) { --$odgr{$_}; push @zodgr, $_ if $odgr{$_} == 0; print " $_(".$odgr{$_}.")" if $debug; } print "\n"; delete $out{$curr}; } print "CYCLIC(".(scalar keys %out)."):\n"; foreach (sort keys %out) { print "\t$_($odgr{$_}):"; foreach (@{$out{$_}}) { print " $_" if exists $out{$_}; } print "\n"; } stxxl-1.3.1/misc/buildbot-configure0000755000175000017500000000641311535366242017171 0ustar andreasandreas#!/bin/sh # --gcc=... # --icpc=... # --with-mcstl # --with-pmode # --with-explicit-pmode # --with-extraflags=... # --with-werror # --with-boost # --with-tpie # --with-leda # --without-btree # --without-unittest # --with-debug=... MODE=false GCC=false ICPC=false MAKE=make MCSTL= PMODE= EXPLICIT_PMODE=no USE_BOOST=no USE_MACOSX=no USE_FREEBSD=no WITH_BTREE=yes WITH_TPIE=no WITH_LEDASM=no WITH_UNITTEST=yes STXXL_WERROR= STXXL_EXTRA= STXXL_DEBUG= ########################################################################### case "`uname -s`" in Darwin) USE_MACOSX=yes MAKE=gmake ;; FreeBSD) USE_FREEBSD=yes MAKE=gmake ;; esac TEMP=`getopt --longoptions gcc:,icpc:,with-mcstl,with-pmode,with-explicit-pmode,with-extraflags:,with-werror,with-boost,with-tpie,with-ledasm,without-btree,without-unittest,with-debug: -- --foo "$@"` if [ $? != 0 ] ; then echo "getopt failed" >&2 ; exit 1 ; fi eval set -- "$TEMP" while true ; do case "$1" in --gcc) MODE=g++ GCC="$2" shift 2 ;; --icpc) MODE=icpc ICPC="$2" shift 2 ;; --with-mcstl) MCSTL=mcstl shift ;; --with-pmode) PMODE=pmode shift ;; --with-explicit-pmode) EXPLICIT_PMODE=yes shift ;; --with-extraflags) STXXL_EXTRA="$2" shift 2 ;; --with-werror) STXXL_WERROR=-Werror shift ;; --with-boost) USE_BOOST=yes shift ;; --with-tpie) WITH_TPIE=yes shift ;; --with-ledasm) WITH_LEDASM=yes shift ;; --without-btree) WITH_BTREE=no shift ;; --without-unittest) WITH_UNITTEST=no shift ;; --with-debug) STXXL_DEBUG="$2" shift 2 ;; --) shift ; break ;; *) echo "Internal error!" ; exit 1 ;; esac done if [ "$MODE" = "false" ]; then echo "Missing mandatory --gcc=... or --icpc=... parameter" 1>&2 exit 1 fi cat > make.settings.local.tmp << EOF MODE = $MODE COMPILER_GCC = $GCC COMPILER_ICPC = $ICPC #STXXL_ROOT = `pwd` MCSTL_ROOT = \$(HOME)/work/mcstl TPIE_ROOT = \$(HOME)/work/lib/\$(UNAME_M)/tpie NICE = USE_PARALLEL_MODE= $EXPLICIT_PMODE PMODE =$PMODE MCSTL =$MCSTL USE_BOOST = $USE_BOOST USE_MACOSX = $USE_MACOSX USE_FREEBSD = $USE_FREEBSD ENABLE_BTREE = $WITH_BTREE ENABLE_BDB = yes ENABLE_TPIE = $WITH_TPIE ENABLE_LEDASM = $WITH_LEDASM ENABLE_UNITTEST = $WITH_UNITTEST ENABLE_LONG_COMPILE = yes DEBUG = $STXXL_DEBUG WARNINGS_EXTRA = $STXXL_WERROR STXXL_EXTRA = STXXL_EXTRA += -DSTXXL_IO_STATS_RESET_FORBIDDEN STXXL_EXTRA += $STXXL_EXTRA EOF if ! cmp -s make.settings.local.tmp make.settings.local ; then test ! -f make.settings.local || mv make.settings.local make.settings.local.old mv make.settings.local.tmp make.settings.local else rm -f make.settings.local.tmp fi test ! -f GNUmakefile || mv GNUmakefile GNUmakefile.old $MAKE -f GNUmakefile.mk GNUmakefile if [ -f GNUmakefile.old ] ; then if cmp -s GNUmakefile GNUmakefile.old ; then mv GNUmakefile.old GNUmakefile else rm -f GNUmakefile.old fi fi echo "#####################################################################" cat make.settings.local echo "#####################################################################" $GCC -v || true $ICPC -V || true echo "#####################################################################" stxxl-1.3.1/misc/iostat-plot.mk0000644000175000017500000001575711525107666016305 0ustar andreasandreas############################################################################ # misc/iostat-plot.mk # # Part of the STXXL. See http://stxxl.sourceforge.net # # Copyright (C) 2008-2011 Andreas Beckmann # # Distributed under the Boost Software License, Version 1.0. # (See accompanying file LICENSE_1_0.txt or copy at # http://www.boost.org/LICENSE_1_0.txt) ############################################################################ # # to record the data, include this file from your Makefile # and use a target like # # my_results.out: # $(IOSTAT_PLOT_RECORD_DATA) -p $(@:.out=) \ # my_program arg1 ... argn > $@ # # and then run # # make my_results.out # make my_results.io.plot # make my_results.cpu.plot # empty ?=# space ?= $(empty) $(empty) comma ?= , ifndef IOSTAT_PLOT_BINDIR IOSTAT_PLOT_BINDIR := $(dir $(lastword $(MAKEFILE_LIST))) endif IOSTAT_PLOT_RECORD_DATA ?= $(IOSTAT_PLOT_BINDIR)/record-load-iostat IOSTAT_PLOT_CONCAT_LINES ?= $(IOSTAT_PLOT_BINDIR)/concat-lines IOSTAT_PLOT_FLOATING_AVERAGE ?= $(IOSTAT_PLOT_BINDIR)/floating-average IOSTAT_PLOT_LINE_IDENTIFIER ?= ^sd IOSTAT_PLOT_LINE_IGNORE_PATTERN ?= IOSTAT_PLOT_CPU_LINE_IDENTIFIER ?= ^$(space)$(space)$(space) IOSTAT_PLOT_DISKS ?= 8 IOSTAT_PLOT_CPUS ?= 8 IOSTAT_PLOT_STRIDE ?= 12 IOSTAT_PLOT_AVERAGE ?= 1 IOSTAT_PLOT_AVERAGE.io ?= $(IOSTAT_PLOT_AVERAGE) IOSTAT_PLOT_AVERAGE.cpu ?= $(IOSTAT_PLOT_AVERAGE) IOSTAT_PLOT_LOAD_REDUCE ?= 0 IOSTAT_PLOT_OFFSET_read_12 ?= 6 IOSTAT_PLOT_OFFSET_write_12 ?= 7 IOSTAT_PLOT_OFFSET_utilize_12 ?= 12 IOSTAT_PLOT_OFFSET_read_14 ?= 8 IOSTAT_PLOT_OFFSET_write_14 ?= 9 IOSTAT_PLOT_OFFSET_utilize_14 ?= ??? IOSTAT_PLOT_DISK_LIST ?= sda sdb sdc sdd sde sdf sdg sdh sdi sdj IOSTAT_PLOT_IO_WITH_UTILIZATION ?= no IOSTAT_PLOT_Y_LABEL.io ?= Bandwidth [MiB/s] IOSTAT_PLOT_Y_LABEL.cpu ?= CPU Usage [%] GNUPLOT_PS_COLOR ?= color solid GNUPLOT_PS_STRING_ESCAPE ?= $(subst _,\\_,$(subst @,\\@,$(subst ~,\\~,$1))) GNUPLOTFILEINFO ?= set label "$(call GNUPLOT_PS_STRING_ESCAPE,$(HOST):$(patsubst $(HOME)/%,~/%,$(CURDIR))/)" at character 0,-1 font ",6" ECHO ?= echo # $1 = first, $2 = increment, $3 = last define gnuplot-column-sequence-sum $(subst $(space),+,$(patsubst %,$$%,$(shell seq $1 $2 $3))) endef # $1 = io | cpu, $2 = numdisks (io) | numcpus (cpu), $3 = stride define template-iostat-gnuplot $(RM) $@ $(ECHO) 'set title "$(subst _, ,$*) (avg=$(IOSTAT_PLOT_AVERAGE.$(strip $1)))"' >> $@ $(ECHO) 'set xlabel "Time [s]"' >> $@ $(ECHO) 'set ylabel "$(IOSTAT_PLOT_Y_LABEL.$(strip $1))"' >> $@ $(if $(and $(filter io,$1),$(filter yes,$(IOSTAT_PLOT_IO_WITH_UTILIZATION))), $(ECHO) 'set y2label "Utilization [%]"' >> $@ $(ECHO) 'set ytics nomirror' >> $@ $(ECHO) 'set y2tics' >> $@ ,$(if $(wildcard $*.waitlog), $(ECHO) 'set y2label "Wait Time [s]"' >> $@ $(ECHO) 'set ytics nomirror' >> $@ $(ECHO) 'set y2tics' >> $@ )) # $(ECHO) 'set style data linespoints' >> $@ $(ECHO) 'set style data lines' >> $@ $(ECHO) 'set macros' >> $@ $(ECHO) 'set pointsize 0.4' >> $@ # $(ECHO) 'set samples 1000' >> $@ $(ECHO) 'set key top left' >> $@ $(ECHO) 'set yrange [0:]' >> $@ $(ECHO) '' >> $@ $(if $(filter io,$1), $(ECHO) 'read = "$(call gnuplot-column-sequence-sum, $(IOSTAT_PLOT_OFFSET_read_$3), $3, $(shell expr $2 '*' $3))"' >> $@ $(ECHO) 'write = "$(call gnuplot-column-sequence-sum, $(IOSTAT_PLOT_OFFSET_write_$3), $3, $(shell expr $2 '*' $3))"' >> $@ $(ECHO) 'utilize = "($(call gnuplot-column-sequence-sum, $(IOSTAT_PLOT_OFFSET_utilize_$3), $3, $(shell expr $2 '*' $3))) / $2"' >> $@ $(ECHO) '' >> $@ $(ECHO) 'plot \' >> $@ $(ECHO) ' "$<" using 0:(@read + @write) title "Read + Write" ls 3$(comma) \' >> $@ $(ECHO) ' "$<" using 0:(@read) title "Read" ls 2$(comma) \' >> $@ $(ECHO) ' "$<" using 0:(@write) title "Write" ls 1$(comma) \' >> $@ $(if $(filter yes,$(IOSTAT_PLOT_IO_WITH_UTILIZATION)), $(ECHO) ' "$<" using 0:(@utilize) title "Utilization" ls 5 axes x1y2$(comma) \' >> $@ ,$(if $(wildcard $*.waitlog), $(ECHO) ' "$*.waitlog" using 1:4 title "Wait Read" ls 5 axes x1y2$(comma) \' >> $@ $(ECHO) ' "$*.waitlog" using 1:5 title "Wait Write" ls 4 axes x1y2$(comma) \' >> $@ )) $(ECHO) ' "not.existing.dummy" using 8:15 notitle' >> $@ ) $(if $(filter cpu,$1), $(ECHO) 'plot \' >> $@ $(ECHO) ' "$(word 2,$^)" using 0:(100*($$1-$(IOSTAT_PLOT_LOAD_REDUCE))/$(strip $2)) title "Load (100% = $2)" ls 5$(comma) \' >> $@ $(ECHO) ' "$<" using 0:($$1+$$2+$$3+$$4) title "Total" ls 4$(comma) \' >> $@ $(ECHO) ' "$<" using 0:2 title "Nice" ls 6$(comma) \' >> $@ $(ECHO) ' "$<" using 0:4 title "Wait" ls 2$(comma) \' >> $@ $(ECHO) ' "$<" using 0:1 title "User" ls 1$(comma) \' >> $@ $(ECHO) ' "$<" using 0:3 title "System" ls 3$(comma) \' >> $@ $(ECHO) ' "$(word 2,$^)" using 0:(100*($$1-$(IOSTAT_PLOT_LOAD_REDUCE))/$(strip $2)) notitle ls 5$(comma) \' >> $@ $(ECHO) ' "not.existing.dummy" using 8:15 notitle' >> $@ ) $(ECHO) '' >> $@ $(ECHO) 'pause -1' >> $@ $(ECHO) '' >> $@ $(ECHO) 'set terminal postscript enhanced $(GNUPLOT_PS_COLOR) 10' >> $@ $(ECHO) 'set output "$*.$(strip $1).eps"' >> $@ $(ECHO) '$(GNUPLOTFILEINFO)' >> $@ $(ECHO) 'replot' >> $@ $(ECHO) '' >> $@ endef %.io-$(IOSTAT_PLOT_AVERAGE.io).dat: %.iostat $(MAKEFILE_LIST) $(pipefail) \ cat $< | \ $(if $(IOSTAT_PLOT_LINE_IGNORE_PATTERN),grep -v '$(IOSTAT_PLOT_LINE_IGNORE_PATTERN)' |) \ $(IOSTAT_PLOT_CONCAT_LINES) '$(IOSTAT_PLOT_LINE_IDENTIFIER)' | \ grep '$(IOSTAT_PLOT_LINE_IDENTIFIER)' | \ tail -n +2 | \ $(IOSTAT_PLOT_FLOATING_AVERAGE) $(IOSTAT_PLOT_AVERAGE.io) > $@ define per-disk-plot-template %.$(disk).io-$$(IOSTAT_PLOT_AVERAGE.io).dat: IOSTAT_PLOT_LINE_IDENTIFIER=^$(disk) %.$(disk).io-$$(IOSTAT_PLOT_AVERAGE.io).plot: IOSTAT_PLOT_DISKS=1 %.$(disk).io-$$(IOSTAT_PLOT_AVERAGE.io).plot: IOSTAT_PLOT_IO_WITH_UTILIZATION=yes %.$(disk).io-$$(IOSTAT_PLOT_AVERAGE.io).dat: %.iostat $$(MAKEFILE_LIST) $$(pipefail) \ cat $$< | \ $$(if $$(IOSTAT_PLOT_LINE_IGNORE_PATTERN),grep -v '$$(IOSTAT_PLOT_LINE_IGNORE_PATTERN)' |) \ $$(IOSTAT_PLOT_CONCAT_LINES) $$(IOSTAT_PLOT_LINE_IDENTIFIER) | \ grep "$$(IOSTAT_PLOT_LINE_IDENTIFIER)" | \ tail -n +2 | \ $$(IOSTAT_PLOT_FLOATING_AVERAGE) $$(IOSTAT_PLOT_AVERAGE.io) > $$@ endef $(foreach disk, $(IOSTAT_PLOT_DISK_LIST),$(eval $(per-disk-plot-template))) %.cpu-$(IOSTAT_PLOT_AVERAGE.cpu).dat: %.iostat $(MAKEFILE_LIST) $(pipefail) \ grep "$(IOSTAT_PLOT_CPU_LINE_IDENTIFIER)" $< | \ tail -n +2 | \ $(IOSTAT_PLOT_FLOATING_AVERAGE) $(IOSTAT_PLOT_AVERAGE.cpu) > $@ %.io-$(IOSTAT_PLOT_AVERAGE.io).plot: %.io-$(IOSTAT_PLOT_AVERAGE.io).dat $(MAKEFILE_LIST) $(call template-iostat-gnuplot,io,$(IOSTAT_PLOT_DISKS),$(IOSTAT_PLOT_STRIDE)) %.io.plot: %.io-$(IOSTAT_PLOT_AVERAGE.io).plot @$(ECHO) Your plot file is: $< %.cpu-$(IOSTAT_PLOT_AVERAGE.cpu).plot: %.cpu-$(IOSTAT_PLOT_AVERAGE.cpu).dat %.loadavg $(MAKEFILE_LIST) $(call template-iostat-gnuplot,cpu,$(IOSTAT_PLOT_CPUS),$(IOSTAT_PLOT_STRIDE)) %.cpu.plot: %.cpu-$(IOSTAT_PLOT_AVERAGE.cpu).plot @$(ECHO) Your plot file is: $< %.io.xplot: %.io-$(IOSTAT_PLOT_AVERAGE.io).plot gnuplot $< %.cpu.xplot: %.cpu-$(IOSTAT_PLOT_AVERAGE.cpu).plot gnuplot $< .SECONDARY: .DELETE_ON_ERROR: stxxl-1.3.1/misc/buildbot-run-tests-minimal0000755000175000017500000000123111337007057020565 0ustar andreasandreas#!/bin/bash variants="stxxl mcstxxl pmstxxl stxxl_boost mcstxxl_boost pmstxxl_boost" ulimit -t 7200 set -o pipefail run_ldd() { cmd="$1.$stxxl.bin" shift test -x $cmd || return 0 echo "==================== ldd $cmd ====================" ldd $cmd } run() { cmd="$1.$stxxl.bin" shift test -x $cmd || return 0 echo "==================== $cmd $@ ====================" echo "[`date`] Start" $cmd "$@" < /dev/null result=$? echo "[`date`] Finish($result)" } for stxxl in $variants do run_ldd common/stxxl_info done for stxxl in $variants do run common/stxxl_info run mng/test_aligned done echo "==================== finished ====================" stxxl-1.3.1/misc/record-load-iostat0000755000175000017500000000275711455522210017077 0ustar andreasandreas#!/bin/sh ############################################################################ # misc/record-load-iostat # # Part of the STXXL. See http://stxxl.sourceforge.net # # Copyright (C) 2008 Andreas Beckmann # # Distributed under the Boost Software License, Version 1.0. # (See accompanying file LICENSE_1_0.txt or copy at # http://www.boost.org/LICENSE_1_0.txt) ############################################################################ # Usage: $0 [ -p outfileprefix ] command PID_IOSTAT="" PID_LOAD="" RETVAL="1" cleanup() { if [ -n "$PID_IOSTAT" ] || [ -n "$PID_LOAD" ]; then kill $PID_IOSTAT $PID_LOAD fi exit $RETVAL } loadavg() { while true do cat /proc/loadavg sleep 1 done } trap cleanup 1 2 3 15 OUTFILEPREFIX=iostat_`hostname`_`date +%F--%H-%M` if [ "$1" = "-p" ]; then OUTFILEPREFIX="$2" shift shift fi if [ -z "$DONT_WAIT_FOR_LOW_LOAD" ]; then # wait at most 120 seconds for load to drop below 1.00 loop="" load=`cut -d. -f1 /proc/loadavg` echo -n "Waiting for load to drop below 1.00 " >/dev/tty while [ "$load" != "0" ] && [ "$loop" != "........................" ] do echo -n "." >/dev/tty sleep 5 loop="$loop." load=`cut -d. -f1 /proc/loadavg` done echo " ==> `cut -d' ' -f1 /proc/loadavg`" >/dev/tty fi #run command passed as the argument concurrently to iostat #dump I/O stat every second iostat -x -m -t 1 >$OUTFILEPREFIX.iostat & PID_IOSTAT=$! loadavg >$OUTFILEPREFIX.loadavg & PID_LOAD=$! "$@" RETVAL=$? cleanup exit $RETVAL stxxl-1.3.1/misc/buildbot-master/0000755000175000017500000000000011536252421016543 5ustar andreasandreasstxxl-1.3.1/misc/buildbot-master/master_secret.py.sample0000644000175000017500000000051511252671370023241 0ustar andreasandreasfrom buildbot.buildslave import BuildSlave linux64full = [ 'foo' ] linux64 = [ 'foo', 'bar' ] linux32 = [ 'foo' ] windows = [ 'foo' ] def protected_settings(c): c['slaves'] = [ BuildSlave("foo", "fooBAR", max_builds=2), BuildSlave("bar", "FOObar", max_builds=2), ] c['slavePortnum'] = 12345 c['debugPassword'] = "foobar" stxxl-1.3.1/misc/buildbot-master/master.cfg0000644000175000017500000011530111531237425020522 0ustar andreasandreas# -*- python -*- # ex: set syntax=python: # This is a sample buildmaster config file. It must be installed as # 'master.cfg' in your buildmaster's base directory (although the filename # can be changed with the --basedir option to 'mktap buildbot master'). # It has one job: define a dictionary named BuildmasterConfig. This # dictionary has a variety of keys to control different aspects of the # buildmaster. They are documented in docs/config.xhtml . # This is the dictionary that the buildmaster pays attention to. We also use # a shorter alias to save typing. c = BuildmasterConfig = {} from master_secret import * protected_settings(c) ####### BUILDSLAVES # the 'slaves' list defines the set of allowable buildslaves. Each element is # a BuildSlave object, which is created with bot-name, bot-password. These # correspond to values given to the buildslave's mktap invocation. from buildbot.buildslave import BuildSlave # these are set in master_secret.py #c['slaves'] = [...] #linux64full = [ ] #linux64 = [ ] #linux32 = [ ] #windows = [ ] # to limit to two concurrent builds on a slave, use # c['slaves'] = [BuildSlave("bot1name", "bot1passwd", max_builds=2)] # 'slavePortnum' defines the TCP port to listen on. This must match the value # configured into the buildslaves (with their --master option) # this is set in master_secret.py #c['slavePortnum'] = 9989 ####### CHANGESOURCES # the 'change_source' setting tells the buildmaster how it should find out # about source code changes. Any class which implements IChangeSource can be # put here: there are several in buildbot/changes/*.py to choose from. #from buildbot.changes.pb import PBChangeSource #c['change_source'] = PBChangeSource() # For example, if you had CVSToys installed on your repository, and your # CVSROOT/freshcfg file had an entry like this: #pb = ConfigurationSet([ # (None, None, None, PBService(userpass=('foo', 'bar'), port=4519)), # ]) # then you could use the following buildmaster Change Source to subscribe to # the FreshCVS daemon and be notified on every commit: # #from buildbot.changes.freshcvs import FreshCVSSource #fc_source = FreshCVSSource("cvs.example.com", 4519, "foo", "bar") #c['change_source'] = fc_source # or, use a PBChangeSource, and then have your repository's commit script run # 'buildbot sendchange', or use contrib/svn_buildbot.py, or # contrib/arch_buildbot.py : # #from buildbot.changes.pb import PBChangeSource #c['change_source'] = PBChangeSource() def split_file_branches(path): pieces = path.split('/') if pieces[0] == 'trunk': return (None, '/'.join(pieces[1:])) elif pieces[0] == 'branches': return ('/'.join(pieces[0:2]), '/'.join(pieces[2:])) else: return None from buildbot.changes.svnpoller import SVNPoller, split_file_branches c['change_source'] = SVNPoller("https://stxxl.svn.sourceforge.net/svnroot/stxxl/", split_file=split_file_branches) # If you wat to use SVNPoller, it might look something like # # Where to get source code changes # from buildbot.changes.svnpoller import SVNPoller # source_code_svn_url='https://svn.myproject.org/bluejay/trunk' # svn_poller = SVNPoller( # svnurl=source_code_svn_url, # pollinterval=60*60, # seconds # histmax=10, # svnbin='/usr/bin/svn', ## ) # c['sources'] = [ svn_poller ] ####### SCHEDULERS ## configure the Schedulers from buildbot.scheduler import Scheduler from buildbot.scheduler import AnyBranchScheduler c['schedulers'] = [] #c['schedulers'].append(Scheduler(name="all", branch=None, # treeStableTimer=2*60, # builderNames=["buildbot-full"])) # SEE BELOW ####### BUILDERS # the 'builders' list defines the Builders. Each one is configured with a # dictionary, using the following keys: # name (required): the name used to describe this builder # slavename (required): which slave to use (must appear in c['bots']) # builddir (required): which subdirectory to run the builder in # factory (required): a BuildFactory to define how the build is run # periodicBuildTime (optional): if set, force a build every N seconds # buildbot/process/factory.py provides several BuildFactory classes you can # start with, which implement build processes for common targets (GNU # autoconf projects, CPAN perl modules, etc). The factory.BuildFactory is the # base class, and is configured with a series of BuildSteps. When the build # is run, the appropriate buildslave is told to execute each Step in turn. # the first BuildStep is typically responsible for obtaining a copy of the # sources. There are source-obtaining Steps in buildbot/steps/source.py for # CVS, SVN, and others. #cvsroot = ":pserver:anonymous@cvs.sourceforge.net:/cvsroot/buildbot" #cvsmodule = "buildbot" from buildbot.process import factory #from buildbot.steps.source import CVS from buildbot.steps import source, shell #from buildbot.steps.source import SVN #from buildbot.steps.shell import Compile from buildbot.steps.python_twisted import Trial #f1 = factory.BuildFactory() #f1.addStep(CVS(cvsroot=cvsroot, cvsmodule=cvsmodule, login="", mode="copy")) #f1.addStep(Compile(command=["python", "./setup.py", "build"])) #f1.addStep(Trial(testChanges=True, testpath=".")) # #b1 = {'name': "buildbot-full", # 'slavename': "bot1name", # 'builddir': "full", # 'factory': f1, # } #c['builders'] = [b1] c['builders'] = [] stxxl_full_builder_names = [] stxxl_trunk_builder_names = [] stxxl_parpipe_builder_names = [] stxxl_branch_builder_names = [] stxxl_trunk_builder_names_delayed = [] stxxl_parpipe_builder_names_delayed = [] stxxl_branch_builder_names_delayed = [] stxxl_svn_update = source.SVN(mode='update', baseURL='https://stxxl.svn.sourceforge.net/svnroot/stxxl/', defaultBranch='trunk') stxxl_svn_copy = source.SVN(mode='copy', baseURL='https://stxxl.svn.sourceforge.net/svnroot/stxxl/', defaultBranch='trunk') stxxl_svn_export = source.SVN(mode='export', baseURL='https://stxxl.svn.sourceforge.net/svnroot/stxxl/', defaultBranch='trunk') stxxl_autoconfigure_test = shell.Configure(command=['misc/buildbot-test-autoconfig'], description='pre-config testing', descriptionDone='pre-config') #stxxl_configure_gcc32 = shell.Configure(command=['misc/buildbot-configure', '--gcc=g++-3.2.x', '--with-werror']) #stxxl_configure_gcc32_boost = shell.Configure(command=['misc/buildbot-configure', '--gcc=g++-3.2.x', '--with-werror', '--with-boost']) stxxl_configure_gcc33 = shell.Configure(command=['misc/buildbot-configure', '--gcc=g++-3.3.x', '--with-werror', '--without-unittest', '--without-btree']) stxxl_configure_gcc33_boost = shell.Configure(command=['misc/buildbot-configure', '--gcc=g++-3.3.x', '--with-werror', '--without-unittest', '--without-btree', '--with-boost']) stxxl_configure_gcc34 = shell.Configure(command=['misc/buildbot-configure', '--gcc=g++-3.4.x', '--with-werror', '--without-unittest']) stxxl_configure_gcc34_boost = shell.Configure(command=['misc/buildbot-configure', '--gcc=g++-3.4.x', '--with-werror', '--without-unittest', '--with-boost']) stxxl_configure_gcc40 = shell.Configure(command=['misc/buildbot-configure', '--gcc=g++-4.0.x', '--with-werror', '--without-unittest']) stxxl_configure_gcc40_boost = shell.Configure(command=['misc/buildbot-configure', '--gcc=g++-4.0.x', '--with-werror', '--without-unittest', '--with-boost']) stxxl_configure_gcc41 = shell.Configure(command=['misc/buildbot-configure', '--gcc=g++-4.1.x', '--with-werror', '--without-unittest']) stxxl_configure_gcc41_boost = shell.Configure(command=['misc/buildbot-configure', '--gcc=g++-4.1.x', '--with-werror', '--without-unittest', '--with-boost']) stxxl_configure_gcc42 = shell.Configure(command=['misc/buildbot-configure', '--gcc=g++-4.2', '--with-mcstl', '--with-werror', '--with-tpie']) stxxl_configure_gcc42_boost = shell.Configure(command=['misc/buildbot-configure', '--gcc=g++-4.2', '--with-mcstl', '--with-werror', '--with-tpie', '--with-boost']) stxxl_configure_gcc42x = shell.Configure(command=['misc/buildbot-configure', '--gcc=g++-4.2.x', '--with-mcstl', '--with-werror', '--with-tpie']) stxxl_configure_gcc42x_boost = shell.Configure(command=['misc/buildbot-configure', '--gcc=g++-4.2.x', '--with-mcstl', '--with-werror', '--with-tpie', '--with-boost']) stxxl_configure_gcc43 = shell.Configure(command=['misc/buildbot-configure', '--gcc=g++-4.3 -std=c++0x', '--with-pmode', '--with-werror', '--with-tpie']) stxxl_configure_gcc43_boost = shell.Configure(command=['misc/buildbot-configure', '--gcc=g++-4.3 -std=c++0x', '--with-pmode', '--with-werror', '--with-tpie', '--with-boost']) stxxl_configure_gcc43o = shell.Configure(command=['misc/buildbot-configure', '--gcc=g++-4.3', '--with-pmode', '--with-werror', '--with-tpie']) stxxl_configure_gcc43o_boost = shell.Configure(command=['misc/buildbot-configure', '--gcc=g++-4.3', '--with-pmode', '--with-werror', '--with-tpie', '--with-boost']) stxxl_configure_gcc43x = shell.Configure(command=['misc/buildbot-configure', '--gcc=g++-4.3.x -std=c++0x', '--with-pmode', '--with-werror', '--with-tpie']) stxxl_configure_gcc43x_boost = shell.Configure(command=['misc/buildbot-configure', '--gcc=g++-4.3.x -std=c++0x', '--with-pmode', '--with-werror', '--with-tpie', '--with-boost']) stxxl_configure_gcc44 = shell.Configure(command=['misc/buildbot-configure', '--gcc=g++-4.4 -std=c++0x', '--with-pmode', '--with-werror', '--with-tpie']) stxxl_configure_gcc44_boost = shell.Configure(command=['misc/buildbot-configure', '--gcc=g++-4.4 -std=c++0x', '--with-pmode', '--with-werror', '--with-tpie', '--with-boost']) stxxl_configure_gcc44_verbose = shell.Configure(command=['misc/buildbot-configure', '--gcc=g++-4.4 -std=c++0x', '--with-pmode', '--with-werror', '--with-tpie', '--with-extraflags=-DSTXXL_FORCE_VERBOSE_LEVEL=9']) stxxl_configure_gcc44_explicit_pmode = shell.Configure(command=['misc/buildbot-configure', '--gcc=g++-4.4 -std=c++0x', '--with-pmode', '--with-werror', '--with-tpie', '--with-explicit-pmode']) stxxl_configure_gcc44o = shell.Configure(command=['misc/buildbot-configure', '--gcc=g++-4.4', '--with-pmode', '--with-werror', '--with-tpie']) stxxl_configure_gcc44o_boost = shell.Configure(command=['misc/buildbot-configure', '--gcc=g++-4.4', '--with-pmode', '--with-werror', '--with-tpie', '--with-boost']) stxxl_configure_gcc44x = shell.Configure(command=['misc/buildbot-configure', '--gcc=g++-4.4.x -std=c++0x', '--with-pmode', '--with-werror', '--with-tpie']) stxxl_configure_gcc44x_boost = shell.Configure(command=['misc/buildbot-configure', '--gcc=g++-4.4.x -std=c++0x', '--with-pmode', '--with-werror', '--with-tpie', '--with-boost']) stxxl_configure_gcc45 = shell.Configure(command=['misc/buildbot-configure', '--gcc=g++-4.5 -std=c++0x', '--with-pmode', '--with-werror', '--with-tpie']) stxxl_configure_gcc45_boost = shell.Configure(command=['misc/buildbot-configure', '--gcc=g++-4.5 -std=c++0x', '--with-pmode', '--with-werror', '--with-tpie', '--with-boost']) stxxl_configure_gcc45o = shell.Configure(command=['misc/buildbot-configure', '--gcc=g++-4.5', '--with-pmode', '--with-werror', '--with-tpie']) stxxl_configure_gcc45o_boost = shell.Configure(command=['misc/buildbot-configure', '--gcc=g++-4.5', '--with-pmode', '--with-werror', '--with-tpie', '--with-boost']) stxxl_configure_gcc45x = shell.Configure(command=['misc/buildbot-configure', '--gcc=g++-4.5.x -std=c++0x', '--with-pmode', '--with-werror', '--with-tpie']) stxxl_configure_gcc45x_boost = shell.Configure(command=['misc/buildbot-configure', '--gcc=g++-4.5.x -std=c++0x', '--with-pmode', '--with-werror', '--with-tpie', '--with-boost']) stxxl_configure_gcc46x = shell.Configure(command=['misc/buildbot-configure', '--gcc=g++-trunk -std=c++0x', '--with-pmode', '--with-tpie']) stxxl_configure_gcc46x_boost = shell.Configure(command=['misc/buildbot-configure', '--gcc=g++-trunk -std=c++0x', '--with-pmode', '--with-tpie', '--with-boost']) stxxl_configure_icpc90 = shell.Configure(command=['misc/buildbot-configure', '--icpc=icpc-9.0 -gcc-name=gcc-3.4.x', '--without-unittest']) #stxxl_configure_icpc91 = shell.Configure(command=['misc/buildbot-configure', '--icpc=icpc-9.1 -gcc-name=gcc-4.1.x', '--without-unittest']) stxxl_configure_icpc91 = shell.Configure(command=['misc/buildbot-configure', '--icpc=icpc-9.1 -gcc-name=gcc-3.4.x', '--without-unittest']) stxxl_configure_icpc100 = shell.Configure(command=['misc/buildbot-configure', '--icpc=icpc-10.0 -gcc-name=needsworkaround', '--with-mcstl']) stxxl_configure_icpc100_boost = shell.Configure(command=['misc/buildbot-configure', '--icpc=icpc-10.0 -gcc-name=needsworkaround', '--with-mcstl', '--with-boost']) stxxl_configure_icpc101 = shell.Configure(command=['misc/buildbot-configure', '--icpc=icpc-10.1 -gcc-name=gcc-4.2.x', '--with-mcstl']) stxxl_configure_icpc101_boost = shell.Configure(command=['misc/buildbot-configure', '--icpc=icpc-10.1 -gcc-name=gcc-4.2.x', '--with-mcstl', '--with-boost']) stxxl_configure_icpc110 = shell.Configure(command=['misc/buildbot-configure', '--icpc=icpc-11.0 -gcc-name=gcc-4.2.x', '--with-mcstl']) stxxl_configure_icpc110_boost = shell.Configure(command=['misc/buildbot-configure', '--icpc=icpc-11.0 -gcc-name=gcc-4.2.x', '--with-mcstl', '--with-boost']) stxxl_configure_icpc111 = shell.Configure(command=['misc/buildbot-configure', '--icpc=icpc-11.1 -gcc-name=gcc-4.2.x', '--with-mcstl']) stxxl_configure_icpc111_boost = shell.Configure(command=['misc/buildbot-configure', '--icpc=icpc-11.1 -gcc-name=gcc-4.2.x', '--with-mcstl', '--with-boost']) stxxl_configure_icpc120o = shell.Configure(command=['misc/buildbot-configure', '--icpc=icpc-12.0 -gcc-name=gcc-4.2.x', '--with-mcstl']) stxxl_configure_icpc120o_boost = shell.Configure(command=['misc/buildbot-configure', '--icpc=icpc-12.0 -gcc-name=gcc-4.2.x', '--with-mcstl', '--with-boost']) stxxl_configure_icpc120 = shell.Configure(command=['misc/buildbot-configure', '--icpc=icpc-12.0 -gcc-name=gcc-4.3.x -std=c++0x', '--with-pmode', '--with-extraflags=-D__aligned__=ignored']) stxxl_configure_icpc120_boost = shell.Configure(command=['misc/buildbot-configure', '--icpc=icpc-12.0 -gcc-name=gcc-4.3.x -std=c++0x', '--with-pmode', '--with-boost', '--with-extraflags=-D__aligned__=ignored']) # -D__aligned__=ignored was suggested by http://software.intel.com/en-us/forums/showthread.php?t=65041 to work around some icpc issue with g++-4.3 headers stxxl_compile = shell.Compile(command=['make', '-f', 'GNUmakefile', '-k', 'lib', 'header-compile-test', 'tests', 'examples'], timeout=3600) stxxl_compile2 = shell.Compile(command=['make', '-f', 'GNUmakefile', '-k', 'lib', 'tests', 'examples'], timeout=3600) stxxl_doxygen = shell.Compile(command=['make', '-f', 'GNUmakefile', 'clean_doxy', 'doxy'], description='doxygening', descriptionDone='doxygen') stxxl_test_minimal = shell.Test(command=['misc/buildbot-run-tests-minimal']) stxxl_configure_msvc_x86 = shell.Configure(command=['echo', 'BOOST_ROOT=C:\\Progra~2\\boost\\current', '>', 'make.settings.local']) #stxxl_configure_msvc_x86 = shell.Configure(command=['echo BOOST_ROOT="C:\\Program Files (x86)\\boost\\current" > make.settings.local']) stxxl_configure_msvc_amd64 = shell.Configure(command=['echo', 'BOOST_ROOT=C:\\Progra~1\\boost\\current', '>', 'make.settings.local']) #stxxl_configure_msvc_amd64 = shell.Configure(command=['echo BOOST_ROOT="C:\\Program Files\\boost\\current" > make.settings.local']) stxxl_compile_msvc8_x86 = shell.Compile(command=['c:\\Program Files (x86)\\Microsoft Visual Studio 8\\VC\\vcvarsall.bat', 'x86', '&&', 'nmake', '/K', 'library_msvc', 'tests_msvc']) stxxl_compile_msvc8_amd64 = shell.Compile(command=['c:\\Program Files (x86)\\Microsoft Visual Studio 8\\VC\\vcvarsall.bat', 'amd64', '&&', 'nmake', '/K', 'library_msvc', 'tests_msvc']) stxxl_compile_msvc9_x86 = shell.Compile(command=['c:\\Program Files (x86)\\Microsoft Visual Studio 9.0\\VC\\vcvarsall.bat', 'x86', '&&', 'nmake', '/K', 'library_msvc', 'tests_msvc']) stxxl_compile_msvc9_amd64 = shell.Compile(command=['c:\\Program Files (x86)\\Microsoft Visual Studio 9.0\\VC\\vcvarsall.bat', 'amd64', '&&', 'nmake', '/K', 'library_msvc', 'tests_msvc']) stxxl_compile_msvc10_x86 = shell.Compile(command=['c:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\VC\\vcvarsall.bat', 'x86', '&&', 'nmake', '/K', 'library_msvc', 'tests_msvc']) stxxl_compile_msvc10_amd64 = shell.Compile(command=['c:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\VC\\vcvarsall.bat', 'amd64', '&&', 'nmake', '/K', 'library_msvc', 'tests_msvc']) f = factory.BuildFactory() f.addStep(stxxl_svn_update) f.addStep(stxxl_configure_gcc44) f.addStep(stxxl_compile) f.addStep(stxxl_doxygen) f.addStep(stxxl_test_minimal) #c['builders'].append( # {'name':'quick', 'slavenames':linux64full, 'builddir':'build-quick', 'factory':f, 'useProgress':False} #) #stxxl_trunk_builder_names.append("quick") f = factory.BuildFactory() f.addStep(stxxl_svn_copy) f.addStep(stxxl_autoconfigure_test) f.addStep(stxxl_configure_gcc44) f.addStep(stxxl_compile) f.addStep(stxxl_doxygen) f.addStep(stxxl_test_minimal) c['builders'].append( {'name':'trunk-linux-full', 'slavenames':linux64full, 'builddir':'trunk-linux-full', 'factory':f } ) stxxl_full_builder_names.append('trunk-linux-full') f = factory.BuildFactory() f.addStep(stxxl_svn_export) f.addStep(stxxl_configure_gcc44) f.addStep(stxxl_compile) f.addStep(stxxl_doxygen) f.addStep(stxxl_test_minimal) #c['builders'].append( # {'name':'export', 'slavenames':linux64full, 'builddir':'export', 'factory':f } #) #stxxl_full_builder_names.append('export') f = factory.BuildFactory() f.addStep(stxxl_svn_update) f.addStep(stxxl_configure_gcc44_verbose) f.addStep(stxxl_compile) f.addStep(stxxl_test_minimal) c['builders'].append( {'name':'trunk-linux-verbose', 'slavenames':linux64full, 'builddir':'trunk-linux-verbose', 'factory':f} ) stxxl_trunk_builder_names.append('trunk-linux-verbose') f = factory.BuildFactory() f.addStep(stxxl_svn_update) f.addStep(stxxl_configure_gcc44_explicit_pmode) f.addStep(stxxl_compile) f.addStep(stxxl_test_minimal) c['builders'].append( {'name':'trunk-linux-explicit-pmode', 'slavenames':linux64full, 'builddir':'trunk-linux-explicit-pmode', 'factory':f} ) stxxl_trunk_builder_names.append('trunk-linux-explicit-pmode') trunk_builders = [] parpipe_builders = [] branch_builders = [] full_builders = [] def addbuilder(slaves, name, steps, progress=False, branches=False, later=False, pp=True, full=False): bf = factory.BuildFactory() for step in steps: bf.addStep(step) trunk_builders.append({'name':'trunk-'+name, 'slavenames':slaves, 'builddir':'trunk-'+name, 'factory':bf, 'useProgress':progress}) if full: stxxl_full_builder_names.append('trunk-'+name) elif not later: stxxl_trunk_builder_names.append('trunk-'+name) else: stxxl_trunk_builder_names_delayed.append('trunk-'+name) if branches: if pp: parpipe_builders.append({'name':'parpipe-'+name, 'slavenames':slaves, 'builddir':'parpipe-'+name, 'factory':bf, 'useProgress':progress}) branch_builders.append({'name':'branch-'+name, 'slavenames':slaves, 'builddir':'branch-'+name, 'factory':bf, 'useProgress':progress}) if not later: if pp: stxxl_parpipe_builder_names.append('parpipe-'+name) stxxl_branch_builder_names.append('branch-'+name) else: if pp: stxxl_parpipe_builder_names_delayed.append('parpipe-'+name) stxxl_branch_builder_names_delayed.append('branch-'+name) return addbuilder(linux64, 'linux-amd64-gcc45-pmode', [stxxl_svn_update, stxxl_configure_gcc45, stxxl_compile, stxxl_doxygen, stxxl_test_minimal], branches=True) #addbuilder(linux64, 'linux-amd64-gcc45-pmode-boost', [stxxl_svn_update, stxxl_configure_gcc45_boost, stxxl_compile, stxxl_test_minimal], branches=True) addbuilder(linux64, 'linux-amd64-gcc44-pmode', [stxxl_svn_update, stxxl_configure_gcc44, stxxl_compile, stxxl_doxygen, stxxl_test_minimal], branches=True) addbuilder(linux64, 'linux-amd64-gcc44-pmode-boost', [stxxl_svn_update, stxxl_configure_gcc44_boost, stxxl_compile, stxxl_test_minimal], branches=True) addbuilder(linux64, 'linux-amd64-gcc43-pmode', [stxxl_svn_update, stxxl_configure_gcc43, stxxl_compile, stxxl_doxygen, stxxl_test_minimal], branches=True) addbuilder(linux64, 'linux-amd64-gcc43-pmode-boost', [stxxl_svn_update, stxxl_configure_gcc43_boost, stxxl_compile, stxxl_test_minimal], branches=True) addbuilder(linux64, 'linux-amd64-gcc42-mcstl', [stxxl_svn_update, stxxl_configure_gcc42, stxxl_compile, stxxl_test_minimal], branches=True) addbuilder(linux64, 'linux-amd64-gcc42-mcstl-boost', [stxxl_svn_update, stxxl_configure_gcc42_boost, stxxl_compile, stxxl_test_minimal], branches=True) addbuilder(linux64, 'linux-amd64-gcc43x-pmode', [stxxl_svn_update, stxxl_configure_gcc43x, stxxl_compile, stxxl_test_minimal], branches=True) addbuilder(linux64, 'linux-amd64-gcc43x-pmode-boost', [stxxl_svn_update, stxxl_configure_gcc43x_boost, stxxl_compile, stxxl_test_minimal], branches=True) addbuilder(linux64, 'linux-amd64-gcc44x-pmode', [stxxl_svn_update, stxxl_configure_gcc44x, stxxl_compile, stxxl_test_minimal], branches=True) addbuilder(linux64, 'linux-amd64-gcc44x-pmode-boost', [stxxl_svn_update, stxxl_configure_gcc44x_boost, stxxl_compile, stxxl_test_minimal], branches=True) addbuilder(linux64, 'linux-amd64-gcc45x-pmode', [stxxl_svn_update, stxxl_configure_gcc45x, stxxl_compile, stxxl_test_minimal], later=True, branches=True) #addbuilder(linux64, 'linux-amd64-gcc45x-pmode-boost', [stxxl_svn_update, stxxl_configure_gcc45x_boost, stxxl_compile, stxxl_test_minimal], later=True, branches=True) addbuilder(linux64, 'linux-amd64-gcc46x-pmode', [stxxl_svn_update, stxxl_configure_gcc46x, stxxl_compile, stxxl_test_minimal], later=True, branches=True) #addbuilder(linux64, 'linux-amd64-gcc46x-pmode-boost', [stxxl_svn_update, stxxl_configure_gcc46x_boost, stxxl_compile, stxxl_test_minimal], later=True, branches=True) addbuilder(linux64, 'linux-amd64-gcc45o-pmode', [stxxl_svn_update, stxxl_configure_gcc45o, stxxl_compile, stxxl_test_minimal], later=True) #addbuilder(linux64, 'linux-amd64-gcc45o-pmode-boost', [stxxl_svn_update, stxxl_configure_gcc45o_boost, stxxl_compile, stxxl_test_minimal], later=True) addbuilder(linux64, 'linux-amd64-gcc44o-pmode', [stxxl_svn_update, stxxl_configure_gcc44o, stxxl_compile, stxxl_test_minimal], later=True) addbuilder(linux64, 'linux-amd64-gcc44o-pmode-boost', [stxxl_svn_update, stxxl_configure_gcc44o_boost, stxxl_compile, stxxl_test_minimal], later=True) #addbuilder(linux64, 'linux-amd64-gcc43o-pmode', [stxxl_svn_update, stxxl_configure_gcc43o, stxxl_compile, stxxl_test_minimal], later=True) #addbuilder(linux64, 'linux-amd64-gcc43o-pmode-boost', [stxxl_svn_update, stxxl_configure_gcc43o_boost, stxxl_compile, stxxl_test_minimal], later=True) addbuilder(linux64, 'linux-amd64-gcc42x-mcstl', [stxxl_svn_update, stxxl_configure_gcc42x, stxxl_compile, stxxl_test_minimal], later=True, branches=True) addbuilder(linux64, 'linux-amd64-gcc42x-mcstl-boost', [stxxl_svn_update, stxxl_configure_gcc42x_boost, stxxl_compile, stxxl_test_minimal], later=True, branches=True) addbuilder(linux64, 'linux-amd64-gcc41', [stxxl_svn_update, stxxl_configure_gcc41, stxxl_compile, stxxl_test_minimal], later=True) #addbuilder(linux64, 'linux-amd64-gcc41-boost', [stxxl_svn_update, stxxl_configure_gcc41_boost, stxxl_compile, stxxl_test_minimal], later=True) addbuilder(linux64, 'linux-amd64-gcc34', [stxxl_svn_update, stxxl_configure_gcc34, stxxl_compile, stxxl_test_minimal], later=True) #addbuilder(linux64, 'linux-amd64-gcc34-boost', [stxxl_svn_update, stxxl_configure_gcc34_boost, stxxl_compile, stxxl_test_minimal], later=True) addbuilder(linux64, 'linux-amd64-icpc120-pmode', [stxxl_svn_update, stxxl_configure_icpc120, stxxl_compile, stxxl_test_minimal], branches=True) addbuilder(linux64, 'linux-amd64-icpc120-pmode-boost', [stxxl_svn_update, stxxl_configure_icpc120_boost, stxxl_compile, stxxl_test_minimal], branches=True) addbuilder(linux64, 'linux-amd64-icpc120-mcstl', [stxxl_svn_update, stxxl_configure_icpc120o, stxxl_compile, stxxl_test_minimal], branches=True) addbuilder(linux64, 'linux-amd64-icpc120-mcstl-boost', [stxxl_svn_update, stxxl_configure_icpc120o_boost, stxxl_compile, stxxl_test_minimal], branches=True) addbuilder(linux64, 'linux-amd64-icpc111-mcstl', [stxxl_svn_update, stxxl_configure_icpc111, stxxl_compile, stxxl_test_minimal], branches=True) addbuilder(linux64, 'linux-amd64-icpc111-mcstl-boost', [stxxl_svn_update, stxxl_configure_icpc111_boost, stxxl_compile, stxxl_test_minimal], branches=True) addbuilder(linux64, 'linux-amd64-icpc110-mcstl', [stxxl_svn_update, stxxl_configure_icpc110, stxxl_compile, stxxl_test_minimal], later=True, branches=True) addbuilder(linux64, 'linux-amd64-icpc110-mcstl-boost', [stxxl_svn_update, stxxl_configure_icpc110_boost, stxxl_compile, stxxl_test_minimal], later=True, branches=True) addbuilder(linux64, 'linux-amd64-icpc101-mcstl', [stxxl_svn_update, stxxl_configure_icpc101, stxxl_compile, stxxl_test_minimal], branches=True) addbuilder(linux64, 'linux-amd64-icpc101-mcstl-boost', [stxxl_svn_update, stxxl_configure_icpc101_boost, stxxl_compile, stxxl_test_minimal], branches=True) addbuilder(linux64, 'linux-amd64-icpc100-mcstl', [stxxl_svn_update, stxxl_configure_icpc100, stxxl_compile, stxxl_test_minimal], later=True, branches=True) addbuilder(linux64, 'linux-amd64-icpc100-mcstl-boost', [stxxl_svn_update, stxxl_configure_icpc100_boost, stxxl_compile, stxxl_test_minimal], later=True, branches=True) addbuilder(linux64, 'linux-amd64-icpc091', [stxxl_svn_update, stxxl_configure_icpc91, stxxl_compile, stxxl_test_minimal], later=True) addbuilder(linux64, 'linux-amd64-icpc090', [stxxl_svn_update, stxxl_configure_icpc90, stxxl_compile, stxxl_test_minimal], later=True) addbuilder(linux32, 'linux-x86-gcc45-pmode', [stxxl_svn_update, stxxl_configure_gcc45, stxxl_compile, stxxl_doxygen, stxxl_test_minimal], branches=True) #addbuilder(linux32, 'linux-x86-gcc45-pmode-boost', [stxxl_svn_update, stxxl_configure_gcc45_boost, stxxl_compile, stxxl_test_minimal], branches=True) addbuilder(linux32, 'linux-x86-gcc44-pmode', [stxxl_svn_update, stxxl_configure_gcc44, stxxl_compile, stxxl_doxygen, stxxl_test_minimal], branches=True) addbuilder(linux32, 'linux-x86-gcc44-pmode-boost', [stxxl_svn_update, stxxl_configure_gcc44_boost, stxxl_compile, stxxl_test_minimal], branches=True) addbuilder(linux32, 'linux-x86-gcc43-pmode', [stxxl_svn_update, stxxl_configure_gcc43, stxxl_compile, stxxl_doxygen, stxxl_test_minimal], branches=True) addbuilder(linux32, 'linux-x86-gcc43-pmode-boost', [stxxl_svn_update, stxxl_configure_gcc43_boost, stxxl_compile, stxxl_test_minimal], branches=True) addbuilder(linux32, 'linux-x86-gcc42-mcstl', [stxxl_svn_update, stxxl_configure_gcc42, stxxl_compile, stxxl_test_minimal], branches=True) addbuilder(linux32, 'linux-x86-gcc42-mcstl-boost', [stxxl_svn_update, stxxl_configure_gcc42_boost, stxxl_compile, stxxl_test_minimal], branches=True) addbuilder(linux32, 'linux-x86-gcc43x-pmode', [stxxl_svn_update, stxxl_configure_gcc43x, stxxl_compile, stxxl_test_minimal], branches=True) addbuilder(linux32, 'linux-x86-gcc43x-pmode-boost', [stxxl_svn_update, stxxl_configure_gcc43x_boost, stxxl_compile, stxxl_test_minimal], branches=True) addbuilder(linux32, 'linux-x86-gcc44x-pmode', [stxxl_svn_update, stxxl_configure_gcc44x, stxxl_compile, stxxl_test_minimal], branches=True) addbuilder(linux32, 'linux-x86-gcc44x-pmode-boost', [stxxl_svn_update, stxxl_configure_gcc44x_boost, stxxl_compile, stxxl_test_minimal], branches=True) addbuilder(linux32, 'linux-x86-gcc45x-pmode', [stxxl_svn_update, stxxl_configure_gcc45x, stxxl_compile, stxxl_test_minimal], later=True, branches=True) #addbuilder(linux32, 'linux-x86-gcc45x-pmode-boost', [stxxl_svn_update, stxxl_configure_gcc45x_boost, stxxl_compile, stxxl_test_minimal], later=True, branches=True) addbuilder(linux32, 'linux-x86-gcc46x-pmode', [stxxl_svn_update, stxxl_configure_gcc46x, stxxl_compile, stxxl_test_minimal], later=True, branches=True) #addbuilder(linux32, 'linux-x86-gcc46x-pmode-boost', [stxxl_svn_update, stxxl_configure_gcc46x_boost, stxxl_compile, stxxl_test_minimal], later=True, branches=True) addbuilder(linux32, 'linux-x86-gcc45o-pmode', [stxxl_svn_update, stxxl_configure_gcc45o, stxxl_compile, stxxl_test_minimal], later=True) #addbuilder(linux32, 'linux-x86-gcc45o-pmode-boost', [stxxl_svn_update, stxxl_configure_gcc45o_boost, stxxl_compile, stxxl_test_minimal], later=True) addbuilder(linux32, 'linux-x86-gcc44o-pmode', [stxxl_svn_update, stxxl_configure_gcc44o, stxxl_compile, stxxl_test_minimal], later=True) addbuilder(linux32, 'linux-x86-gcc44o-pmode-boost', [stxxl_svn_update, stxxl_configure_gcc44o_boost, stxxl_compile, stxxl_test_minimal], later=True) #addbuilder(linux32, 'linux-x86-gcc43o-pmode', [stxxl_svn_update, stxxl_configure_gcc43o, stxxl_compile, stxxl_test_minimal], later=True) #addbuilder(linux32, 'linux-x86-gcc43o-pmode-boost', [stxxl_svn_update, stxxl_configure_gcc43o_boost, stxxl_compile, stxxl_test_minimal], later=True) addbuilder(linux32, 'linux-x86-gcc42x-mcstl', [stxxl_svn_update, stxxl_configure_gcc42x, stxxl_compile, stxxl_test_minimal], later=True, branches=True) addbuilder(linux32, 'linux-x86-gcc42x-mcstl-boost', [stxxl_svn_update, stxxl_configure_gcc42x_boost, stxxl_compile, stxxl_test_minimal], later=True, branches=True) addbuilder(linux32, 'linux-x86-gcc41', [stxxl_svn_update, stxxl_configure_gcc41, stxxl_compile, stxxl_test_minimal], later=True) #addbuilder(linux32, 'linux-x86-gcc41-boost', [stxxl_svn_update, stxxl_configure_gcc41_boost, stxxl_compile, stxxl_test_minimal], later=True) addbuilder(linux32, 'linux-x86-gcc40', [stxxl_svn_update, stxxl_configure_gcc40, stxxl_compile, stxxl_test_minimal], later=True) #addbuilder(linux32, 'linux-x86-gcc40-boost', [stxxl_svn_update, stxxl_configure_gcc40_boost, stxxl_compile, stxxl_test_minimal], later=True) addbuilder(linux32, 'linux-x86-gcc34', [stxxl_svn_update, stxxl_configure_gcc34, stxxl_compile, stxxl_test_minimal], later=True) #addbuilder(linux32, 'linux-x86-gcc34-boost', [stxxl_svn_update, stxxl_configure_gcc34_boost, stxxl_compile, stxxl_test_minimal], later=True) addbuilder(linux32, 'linux-x86-gcc33', [stxxl_svn_update, stxxl_configure_gcc33, stxxl_compile2, stxxl_test_minimal], later=True) #addbuilder(linux32, 'linux-x86-gcc33-boost', [stxxl_svn_update, stxxl_configure_gcc33_boost, stxxl_compile2, stxxl_test_minimal], later=True) #addbuilder(linux32, 'linux-x86-gcc32', [stxxl_svn_update, stxxl_configure_gcc32, stxxl_compile, stxxl_test_minimal], later=True) #addbuilder(linux32, 'linux-x86-gcc32-boost', [stxxl_svn_update, stxxl_configure_gcc32_boost, stxxl_compile, stxxl_test_minimal], later=True) addbuilder(linux32, 'linux-x86-icpc120-pmode', [stxxl_svn_update, stxxl_configure_icpc120, stxxl_compile, stxxl_test_minimal], branches=True) addbuilder(linux32, 'linux-x86-icpc120-pmode-boost', [stxxl_svn_update, stxxl_configure_icpc120_boost, stxxl_compile, stxxl_test_minimal], branches=True) addbuilder(linux32, 'linux-x86-icpc120-mcstl', [stxxl_svn_update, stxxl_configure_icpc120o, stxxl_compile, stxxl_test_minimal], branches=True) addbuilder(linux32, 'linux-x86-icpc120-mcstl-boost', [stxxl_svn_update, stxxl_configure_icpc120o_boost, stxxl_compile, stxxl_test_minimal], branches=True) addbuilder(linux32, 'linux-x86-icpc111-mcstl', [stxxl_svn_update, stxxl_configure_icpc111, stxxl_compile, stxxl_test_minimal], branches=True) addbuilder(linux32, 'linux-x86-icpc111-mcstl-boost', [stxxl_svn_update, stxxl_configure_icpc111_boost, stxxl_compile, stxxl_test_minimal], branches=True) addbuilder(linux32, 'linux-x86-icpc110-mcstl', [stxxl_svn_update, stxxl_configure_icpc110, stxxl_compile, stxxl_test_minimal], later=True, branches=True) addbuilder(linux32, 'linux-x86-icpc110-mcstl-boost', [stxxl_svn_update, stxxl_configure_icpc110_boost, stxxl_compile, stxxl_test_minimal], later=True, branches=True) addbuilder(linux32, 'linux-x86-icpc101-mcstl', [stxxl_svn_update, stxxl_configure_icpc101, stxxl_compile, stxxl_test_minimal], branches=True) addbuilder(linux32, 'linux-x86-icpc101-mcstl-boost', [stxxl_svn_update, stxxl_configure_icpc101_boost, stxxl_compile, stxxl_test_minimal], branches=True) addbuilder(linux32, 'linux-x86-icpc100-mcstl', [stxxl_svn_update, stxxl_configure_icpc100, stxxl_compile, stxxl_test_minimal], later=True, branches=True) addbuilder(linux32, 'linux-x86-icpc100-mcstl-boost', [stxxl_svn_update, stxxl_configure_icpc100_boost, stxxl_compile, stxxl_test_minimal], later=True, branches=True) addbuilder(linux32, 'linux-x86-icpc091', [stxxl_svn_update, stxxl_configure_icpc91, stxxl_compile, stxxl_test_minimal], later=True) addbuilder(linux32, 'linux-x86-icpc090', [stxxl_svn_update, stxxl_configure_icpc90, stxxl_compile, stxxl_test_minimal], later=True) addbuilder(windows, 'win32-msvc8', [stxxl_svn_update, stxxl_configure_msvc_x86, stxxl_compile_msvc8_x86], branches=True, pp=True) addbuilder(windows, 'win64-msvc8', [stxxl_svn_update, stxxl_configure_msvc_amd64, stxxl_compile_msvc8_amd64], branches=True, pp=True) addbuilder(windows, 'win32-msvc9', [stxxl_svn_update, stxxl_configure_msvc_x86, stxxl_compile_msvc9_x86], branches=True, pp=True) addbuilder(windows, 'win64-msvc9', [stxxl_svn_update, stxxl_configure_msvc_amd64, stxxl_compile_msvc9_amd64], branches=True, pp=True) addbuilder(windows, 'win32-msvc10', [stxxl_svn_update, stxxl_configure_msvc_x86, stxxl_compile_msvc10_x86], branches=True, pp=True) addbuilder(windows, 'win64-msvc10', [stxxl_svn_update, stxxl_configure_msvc_amd64, stxxl_compile_msvc10_amd64], branches=True, pp=True) addbuilder(windows, 'win64-msvc9-full', [stxxl_svn_copy, stxxl_configure_msvc_amd64, stxxl_compile_msvc9_amd64], pp=False, full=True) c['builders'].extend(trunk_builders) c['builders'].extend(parpipe_builders) c['builders'].extend(branch_builders) #f = factory.BuildFactory() #f.addStep(stxxl_svn_update) #f.addStep(shell.Compile(command=['nmake', 'library_msvc', 'tests_msvc'])) #c['builders'].append({'name':'win64-msvc9', 'slavenames':windows, 'builddir':'win64-msvc9', 'factory':f }) #stxxl_trunk_builder_names.append('win64-msvc9') #c['builders'].append({'name':'branch-win64-msvc9', 'slavenames':windows, 'builddir':'branch-win64-msvc9', 'factory':f }) #stxxl_branch_builder_names.append('branch-win64-msvc9') branches = [ 'branches/comparison_based_stable_sort', 'branches/unordered_map', 'branches/posixaio', 'branches/kernelaio', 'branches/matrix', ] # svn puller @ 10 minutes c['schedulers'].append(Scheduler(name="full builds", branch=None, treeStableTimer=66*60, builderNames=stxxl_full_builder_names)) c['schedulers'].append(Scheduler(name="trunk builds", branch=None, treeStableTimer=1*60, builderNames=stxxl_trunk_builder_names)) c['schedulers'].append(Scheduler(name="trunk builds delayed", branch=None, treeStableTimer=91*60, builderNames=stxxl_trunk_builder_names_delayed)) c['schedulers'].append(AnyBranchScheduler(name="parpipe builds", branches=["branches/parallel_pipelining", 'branches/parallel_pipelining_integration'], treeStableTimer=1*60, builderNames=stxxl_parpipe_builder_names)) c['schedulers'].append(AnyBranchScheduler(name="parpipe builds delayed", branches=["branches/parallel_pipelining", 'branches/parallel_pipelining_integration'], treeStableTimer=121*60, builderNames=stxxl_parpipe_builder_names_delayed)) c['schedulers'].append(AnyBranchScheduler(name="branch builds", branches=branches, treeStableTimer=11*60, builderNames=stxxl_branch_builder_names)) c['schedulers'].append(AnyBranchScheduler(name="branch builds delayed", branches=branches, treeStableTimer=121*60, builderNames=stxxl_branch_builder_names_delayed)) ####### STATUS TARGETS # 'status' is a list of Status Targets. The results of each build will be # pushed to these targets. buildbot/status/*.py has a variety to choose from, # including web pages, email senders, and IRC bots. c['status'] = [] # Use allowForce=True (boolean, not a string. ie: not 'True') to allow # Forcing Builds in the Web User Interface. The default is False. # from buildbot.status import html # c['status'].append(html.WebStatus(http_port=8010,allowForce=True)) from buildbot.status import html #c['status'].append(html.WebStatus(http_port=8010)) c['status'].append(html.WebStatus(http_port="tcp:8010:interface=127.0.0.1", allowForce=False)) c['status'].append(html.WebStatus(http_port="tcp:8011:interface=127.0.0.1", allowForce=True)) # from buildbot.status import mail # c['status'].append(mail.MailNotifier(fromaddr="buildbot@localhost", # extraRecipients=["builds@example.com"], # sendToInterestedUsers=False)) # # from buildbot.status import words # c['status'].append(words.IRC(host="irc.example.com", nick="bb", # channels=["#example"])) # # from buildbot.status import client # c['status'].append(client.PBListener(9988)) ####### DEBUGGING OPTIONS # if you set 'debugPassword', then you can connect to the buildmaster with # the diagnostic tool in contrib/debugclient.py . From this tool, you can # manually force builds and inject changes, which may be useful for testing # your buildmaster without actually committing changes to your repository (or # before you have a functioning 'sources' set up). The debug tool uses the # same port number as the slaves do: 'slavePortnum'. # this is set in master_secret.py #c['debugPassword'] = "debugpassword" # if you set 'manhole', you can ssh into the buildmaster and get an # interactive python shell, which may be useful for debugging buildbot # internals. It is probably only useful for buildbot developers. You can also # use an authorized_keys file, or plain telnet. #from buildbot import manhole #c['manhole'] = manhole.PasswordManhole("tcp:9999:interface=127.0.0.1", # "admin", "password") ####### PROJECT IDENTITY # the 'projectName' string will be used to describe the project that this # buildbot is working on. For example, it is used as the title of the # waterfall HTML page. The 'projectURL' string will be used to provide a link # from buildbot HTML pages to your project's home page. c['projectName'] = "STXXL" c['projectURL'] = "http://stxxl.sourceforge.net/" # the 'buildbotURL' string should point to the location where the buildbot's # internal web server (usually the html.Waterfall page) is visible. This # typically uses the port number set in the Waterfall 'status' entry, but # with an externally-visible host name which the buildbot cannot figure out # without some help. c['buildbotURL'] = "http://localhost:8010/" stxxl-1.3.1/misc/buildbot-master/master.cfg.sample0000644000175000017500000001645711252670721022016 0ustar andreasandreas# -*- python -*- # ex: set syntax=python: # This is a sample buildmaster config file. It must be installed as # 'master.cfg' in your buildmaster's base directory (although the filename # can be changed with the --basedir option to 'mktap buildbot master'). # It has one job: define a dictionary named BuildmasterConfig. This # dictionary has a variety of keys to control different aspects of the # buildmaster. They are documented in docs/config.xhtml . # This is the dictionary that the buildmaster pays attention to. We also use # a shorter alias to save typing. c = BuildmasterConfig = {} ####### BUILDSLAVES # the 'slaves' list defines the set of allowable buildslaves. Each element is # a BuildSlave object, which is created with bot-name, bot-password. These # correspond to values given to the buildslave's mktap invocation. from buildbot.buildslave import BuildSlave c['slaves'] = [BuildSlave("bot1name", "bot1passwd")] # to limit to two concurrent builds on a slave, use # c['slaves'] = [BuildSlave("bot1name", "bot1passwd", max_builds=2)] # 'slavePortnum' defines the TCP port to listen on. This must match the value # configured into the buildslaves (with their --master option) c['slavePortnum'] = 9989 ####### CHANGESOURCES # the 'change_source' setting tells the buildmaster how it should find out # about source code changes. Any class which implements IChangeSource can be # put here: there are several in buildbot/changes/*.py to choose from. from buildbot.changes.pb import PBChangeSource c['change_source'] = PBChangeSource() # For example, if you had CVSToys installed on your repository, and your # CVSROOT/freshcfg file had an entry like this: #pb = ConfigurationSet([ # (None, None, None, PBService(userpass=('foo', 'bar'), port=4519)), # ]) # then you could use the following buildmaster Change Source to subscribe to # the FreshCVS daemon and be notified on every commit: # #from buildbot.changes.freshcvs import FreshCVSSource #fc_source = FreshCVSSource("cvs.example.com", 4519, "foo", "bar") #c['change_source'] = fc_source # or, use a PBChangeSource, and then have your repository's commit script run # 'buildbot sendchange', or use contrib/svn_buildbot.py, or # contrib/arch_buildbot.py : # #from buildbot.changes.pb import PBChangeSource #c['change_source'] = PBChangeSource() # If you wat to use SVNPoller, it might look something like # # Where to get source code changes # from buildbot.changes.svnpoller import SVNPoller # source_code_svn_url='https://svn.myproject.org/bluejay/trunk' # svn_poller = SVNPoller( # svnurl=source_code_svn_url, # pollinterval=60*60, # seconds # histmax=10, # svnbin='/usr/bin/svn', ## ) # c['sources'] = [ svn_poller ] ####### SCHEDULERS ## configure the Schedulers from buildbot.scheduler import Scheduler c['schedulers'] = [] c['schedulers'].append(Scheduler(name="all", branch=None, treeStableTimer=2*60, builderNames=["buildbot-full"])) ####### BUILDERS # the 'builders' list defines the Builders. Each one is configured with a # dictionary, using the following keys: # name (required): the name used to describe this builder # slavename (required): which slave to use (must appear in c['bots']) # builddir (required): which subdirectory to run the builder in # factory (required): a BuildFactory to define how the build is run # periodicBuildTime (optional): if set, force a build every N seconds # buildbot/process/factory.py provides several BuildFactory classes you can # start with, which implement build processes for common targets (GNU # autoconf projects, CPAN perl modules, etc). The factory.BuildFactory is the # base class, and is configured with a series of BuildSteps. When the build # is run, the appropriate buildslave is told to execute each Step in turn. # the first BuildStep is typically responsible for obtaining a copy of the # sources. There are source-obtaining Steps in buildbot/steps/source.py for # CVS, SVN, and others. cvsroot = ":pserver:anonymous@cvs.sourceforge.net:/cvsroot/buildbot" cvsmodule = "buildbot" from buildbot.process import factory from buildbot.steps.source import CVS from buildbot.steps.shell import Compile from buildbot.steps.python_twisted import Trial f1 = factory.BuildFactory() f1.addStep(CVS(cvsroot=cvsroot, cvsmodule=cvsmodule, login="", mode="copy")) f1.addStep(Compile(command=["python", "./setup.py", "build"])) f1.addStep(Trial(testChanges=True, testpath=".")) b1 = {'name': "buildbot-full", 'slavename': "bot1name", 'builddir': "full", 'factory': f1, } c['builders'] = [b1] ####### STATUS TARGETS # 'status' is a list of Status Targets. The results of each build will be # pushed to these targets. buildbot/status/*.py has a variety to choose from, # including web pages, email senders, and IRC bots. c['status'] = [] # Use allowForce=True (boolean, not a string. ie: not 'True') to allow # Forcing Builds in the Web User Interface. The default is False. # from buildbot.status import html # c['status'].append(html.WebStatus(http_port=8010,allowForce=True)) from buildbot.status import html c['status'].append(html.WebStatus(http_port=8010)) # from buildbot.status import mail # c['status'].append(mail.MailNotifier(fromaddr="buildbot@localhost", # extraRecipients=["builds@example.com"], # sendToInterestedUsers=False)) # # from buildbot.status import words # c['status'].append(words.IRC(host="irc.example.com", nick="bb", # channels=["#example"])) # # from buildbot.status import client # c['status'].append(client.PBListener(9988)) ####### DEBUGGING OPTIONS # if you set 'debugPassword', then you can connect to the buildmaster with # the diagnostic tool in contrib/debugclient.py . From this tool, you can # manually force builds and inject changes, which may be useful for testing # your buildmaster without actually committing changes to your repository (or # before you have a functioning 'sources' set up). The debug tool uses the # same port number as the slaves do: 'slavePortnum'. #c['debugPassword'] = "debugpassword" # if you set 'manhole', you can ssh into the buildmaster and get an # interactive python shell, which may be useful for debugging buildbot # internals. It is probably only useful for buildbot developers. You can also # use an authorized_keys file, or plain telnet. #from buildbot import manhole #c['manhole'] = manhole.PasswordManhole("tcp:9999:interface=127.0.0.1", # "admin", "password") ####### PROJECT IDENTITY # the 'projectName' string will be used to describe the project that this # buildbot is working on. For example, it is used as the title of the # waterfall HTML page. The 'projectURL' string will be used to provide a link # from buildbot HTML pages to your project's home page. c['projectName'] = "Buildbot" c['projectURL'] = "http://buildbot.sourceforge.net/" # the 'buildbotURL' string should point to the location where the buildbot's # internal web server (usually the html.Waterfall page) is visible. This # typically uses the port number set in the Waterfall 'status' entry, but # with an externally-visible host name which the buildbot cannot figure out # without some help. c['buildbotURL'] = "http://localhost:8010/" stxxl-1.3.1/misc/diskbench.mk0000644000175000017500000002063211522525142015732 0ustar andreasandreas############################################################################ # misc/diskbench.mk # # Part of the STXXL. See http://stxxl.sourceforge.net # # Copyright (C) 2008-2011 Andreas Beckmann # # Distributed under the Boost Software License, Version 1.0. # (See accompanying file LICENSE_1_0.txt or copy at # http://www.boost.org/LICENSE_1_0.txt) ############################################################################ HOST ?= unknown FILE_SIZE ?= $(or $(SIZE),100) # GiB BLOCK_SIZE ?= $(or $(STEP),256) # MiB BATCH_SIZE ?= 1 # blocks DIRECT_IO ?= yes # unset to disable O_DIRECT SYNC_IO ?= no # set to 'yes' to enable O_SYNC|O_DSYNC|O_RSYNC FILE_TYPE ?= syscall FILE_RESIZE ?= no disk2file ?= /stxxl/sd$1/stxxl DISKS_1by1 ?= a b c d DISKS_a ?= a DISKS_ab ?= a b DISKS_abcd ?= a b c d DISKS_a_ro ?= a FLAGS_a_ro ?= R DISKS ?= abcd $(DISKS_1by1) ab a_ro SIP_NUM_BLOCKS ?= 0 SIP_CHUNK_BLOCKS?= 1 SIP_BLOCK_SIZE ?= 0 DISKBENCH_TITLE ?= STXXL Disk Benchmark $(DISKNAME) B=$(strip $(BATCH_SIZE))x$(call format_block_size,$(BLOCK_SIZE)) @ $(HOST) DISKAVG_TITLE ?= STXXL Disk Benchmark $(DISKNAME) @ $(HOST)$(if $(DISKNAME2),\n$(DISKNAME2)) ifndef MISC_BINDIR MISC_BINDIR := $(dir $(lastword $(MAKEFILE_LIST))) endif DISKBENCH_BINDIR?= $(MISC_BINDIR)/../io DISKBENCH ?= benchmark_disks.stxxl.bin SCATTERINPLACE ?= iobench_scatter_in_place.stxxl.bin ECHO ?= echo pipefail ?= set -o pipefail; $(foreach d,$(DISKS_1by1),$(eval DISKS_$d ?= $d)) ifeq ($(SHELL),/bin/sh) SHELL = bash endif DISKBENCH_FLAGS += $(if $(filter y yes Y YES,$(DIRECT_IO)),,--no-direct) DISKBENCH_FLAGS += $(if $(filter y yes Y YES,$(SYNC_IO)),--sync) DISKBENCH_FLAGS += --file-type=$(strip $(FILE_TYPE)) DISKBENCH_FLAGS += $(if $(filter y yes Y YES,$(FILE_RESIZE)),--resize) define do-some-disks $(if $(filter ???,$(strip $(BLOCK_SIZE))),$(error ERROR: BLOCK_SIZE=$(strip $(BLOCK_SIZE)))) -$(pipefail) \ $(if $(IOSTAT_PLOT_RECORD_DATA),$(IOSTAT_PLOT_RECORD_DATA) -p $(@:.log=)) \ $(DISKBENCH_BINDIR)/$(DISKBENCH) $(DISKBENCH_FLAGS) 0 $(strip $(FILE_SIZE)) $(strip $(BLOCK_SIZE)) $(strip $(BATCH_SIZE)) $(FLAGS_$*) $(FLAGS_EX) $(foreach d,$(DISKS_$*),$(call disk2file,$d)) | tee $@ endef define do-some-disks-sip -$(pipefail) \ $(if $(IOSTAT_PLOT_RECORD_DATA),$(IOSTAT_PLOT_RECORD_DATA) -p $(@:.log=)) \ $(DISKBENCH_BINDIR)/$(SCATTERINPLACE) $(strip $(SIP_NUM_BLOCKS)) $(strip $(SIP_CHUNK_BLOCKS)) $(strip $(SIP_BLOCK_SIZE)) $(foreach d,$(DISKS_$*),$(call disk2file,$d)) | tee $@ endef $(HOST)-%.cr.log: $(if $(keep-old-file),,$(RM) $(foreach d,$(DISKS_$*),$(call disk2file,$d))) $(do-some-disks) $(HOST)-%.crx.log: FLAGS_EX = W $(HOST)-%.crx.log: $(if $(keep-old-file),,$(RM) $(foreach d,$(DISKS_$*),$(call disk2file,$d))) $(do-some-disks) # interleaved write-read-test $(HOST)-%.wr.log: $(do-some-disks) # scanning write $(HOST)-%.wrx.log: FLAGS_EX = W $(HOST)-%.wrx.log: $(do-some-disks) # scanning read $(HOST)-%.rdx.log: FLAGS_EX = R $(HOST)-%.rdx.log: $(do-some-disks) # scatter-in-place $(HOST)-%.sip.log: $(do-some-disks-sip) all: crx wr ex crx: $(foreach d,$(DISKS_1by1),$(HOST)-$d.crx.log) cr: $(foreach d,$(DISKS_1by1),$(HOST)-$d.cr.log) cr+: $(foreach d,$(DISKS),$(HOST)-$d.crx.log) wr: $(foreach d,$(DISKS),$(HOST)-$d.wr.log) wrx: $(foreach d,$(DISKS_1by1),$(HOST)-$d.wrx.log) wr+: $(foreach d,$(DISKS),$(HOST)-$d.wrx.log) rdx: $(foreach d,$(DISKS_1by1),$(HOST)-$d.rdx.log) rd+: $(foreach d,$(DISKS),$(HOST)-$d.rdx.log) ex: $(foreach d,$(DISKS_1by1),$(HOST)-$d.wrx.log $(HOST)-$d.rdx.log) ex+: $(foreach d,$(DISKS),$(HOST)-$d.wrx.log $(HOST)-$d.rdx.log) sip: $(foreach d,$(DISKS_1by1),$(HOST)-$d.sip.log) all-sizes-targets ?= cr+ wr ex+ all-sizes: for d in $(wildcard 0016iMB 0064MB 0004MB 0256MB 0001MB 1024MB *MB) ; do make -C $$d $(all-sizes-targets) ; done all-sizes-raw: keep-old-file=1 all-sizes-raw: all-sizes plot: $(HOST).gnuplot gnuplot $< dotplot: $(HOST).d.gnuplot gnuplot $< avgplot: $(HOST)-avg.gnuplot gnuplot $< avg3plot: $(HOST)-avg3.gnuplot gnuplot $< # $1 = logfile, $2 = column extract_average = $(if $(wildcard $1),$(shell grep ' Average over ' $1 | awk '{ print $$($2+1) }'),......) # $1 = logfile, $2 = disk, $3 = column, $4 = label # (does not plot if avg = nan) define plotline $(if $(wildcard $1),$(if $(filter nan,$(call extract_average,$1,$3)),,$(ECHO) ' "$1" using ($$3/1024):($$$3) w l title "$2 $4 ($(call extract_average,$1,$3))", \' >> $@)) endef # $1 = logfile, $2 = disk define plotline-cr1 $(call plotline,$1,$2,7,cr1) endef define plotline-cr $(call plotline,$1,$2,7,cr) endef define plotline-crx $(call plotline,$1,$2,7,crx) endef define plotline-wr $(call plotline,$1,$2,7,wr) endef define plotline-rd $(call plotline,$1,$2,14,rd) endef define plotline-wrx $(call plotline,$1,$2,7,wrx) endef define plotline-rdx $(call plotline,$1,$2,14,rdx) endef # $1 = disk letter disk2label ?= sd$1 disks2label ?= sd[$1] DISKNAME ?= unknown disk DISKNAME2 ?=# optional second line describing the test environment PLOTXMAX ?= 475 PLOTYMAX ?= 120 AVGPLOTYMAX ?= $(PLOTYMAX) fmt_block_size_2560000B ?= 2.5 fmt_block_size_12800000B ?= 12.5 fmt_block_size_51200000B ?= 50 format_block_size = $(or $(fmt_block_size_$(strip $1)),$(strip $1))MiB $(HOST).gnuplot: $(MAKEFILE_LIST) $(wildcard *.log) $(RM) $@ $(ECHO) 'set title "$(DISKBENCH_TITLE)"' >> $@ $(ECHO) 'set xlabel "Disk offset [GiB]"' >> $@ $(ECHO) 'set ylabel "Bandwidth per disk [MiB/s]"' >> $@ $(ECHO) '' >> $@ $(ECHO) 'plot [0:$(PLOTXMAX)] [0:$(PLOTYMAX)] \' >> $@ $(foreach d,$(DISKS_1by1),\ $(call plotline-cr1,$(HOST)-$d.cr1.log,$(call disk2label,$d)) \ $(call plotline-crx,$(HOST)-$d.crx.log,$(call disk2label,$d)) \ $(call plotline-cr,$(HOST)-$d.cr.log,$(call disk2label,$d)) \ $(call plotline-wr,$(HOST)-$d.wr1.log,$(call disk2label,$d)) \ $(call plotline-rd,$(HOST)-$d.wr1.log,$(call disk2label,$d)) \ $(call plotline-wr,$(HOST)-$d.wr.log,$(call disk2label,$d)) \ $(call plotline-rd,$(HOST)-$d.wr.log,$(call disk2label,$d)) \ $(call plotline-wrx,$(HOST)-$d.wrx.log,$(call disk2label,$d)) \ $(call plotline-rdx,$(HOST)-$d.rdx.log,$(call disk2label,$d)) \ ) $(foreach d,$(filter-out $(DISKS_1by1),$(DISKS)),\ $(call plotline-crx,$(HOST)-$d.crx.log,$(call disks2label,$d)) \ $(call plotline-wr,$(HOST)-$d.wr.log,$(call disks2label,$d)) \ $(call plotline-rd,$(HOST)-$d.wr.log,$(call disks2label,$d)) \ $(call plotline-wrx,$(HOST)-$d.wrx.log,$(call disks2label,$d)) \ $(call plotline-rdx,$(HOST)-$d.rdx.log,$(call disks2label,$d)) \ ) $(ECHO) ' "nothing" notitle' >> $@ $(ECHO) '' >> $@ $(ECHO) 'pause -1' >> $@ $(ECHO) '' >> $@ $(ECHO) 'set title "$(call GNUPLOT_PS_STRING_ESCAPE,$(DISKBENCH_TITLE))"' >> $@ $(ECHO) 'set term postscript enhanced $(GNUPLOT_PS_COLOR) 10' >> $@ $(ECHO) 'set output "$(HOST).ps"' >> $@ $(ECHO) '$(GNUPLOTFILEINFO)' >> $@ $(ECHO) 'replot' >> $@ $(HOST).d.gnuplot: $(HOST).gnuplot sed -e 's/ w l / w d lw 2 /' $< > $@ $(HOST)-avg.dat: $(MISC_BINDIR)/diskbench-avgdat.sh $(wildcard *KB/*.log *MB/*.log) $(MISC_BINDIR)/diskbench-avgdat.sh $(wildcard *KB *MB) > $@ $(HOST)-avg.gnuplot: $(HOST)-avg.dat $(MAKEFILE_LIST) $(RM) $@ $(ECHO) 'set title "$(DISKAVG_TITLE)"' >> $@ $(ECHO) 'set xlabel "Block Size [MiB]"' >> $@ $(ECHO) 'set ylabel "Average Sequential Bandwidth [MiB/s]"' >> $@ $(ECHO) 'set key bottom' >> $@ $(ECHO) '' >> $@ $(ECHO) 'plot [] [0:$(AVGPLOTYMAX)] \' >> $@ $(ECHO) ' "$(HOST)-avg.dat" using 0:2:xtic(1) w lp lt 1 pt 1 title "crx", \' >> $@ $(ECHO) ' "$(HOST)-avg.dat" using 0:3:xtic(1) w lp lt 2 pt 2 title "wr", \' >> $@ $(ECHO) ' "$(HOST)-avg.dat" using 0:4:xtic(1) w lp lt 3 pt 3 title "rd", \' >> $@ $(ECHO) ' "$(HOST)-avg.dat" using 0:5:xtic(1) w lp lt 4 pt 4 title "wrx", \' >> $@ $(ECHO) ' "$(HOST)-avg.dat" using 0:6:xtic(1) w lp lt 5 pt 5 title "rdx", \' >> $@ $(ECHO) ' "nothing" notitle' >> $@ $(ECHO) '' >> $@ $(ECHO) 'pause -1' >> $@ $(ECHO) '' >> $@ $(ECHO) 'set term png size 800,600' >> $@ $(ECHO) 'set output "$(HOST)-avg.png"' >> $@ $(ECHO) 'replot' >> $@ $(ECHO) '' >> $@ $(ECHO) 'set title "$(call GNUPLOT_PS_STRING_ESCAPE,$(DISKAVG_TITLE))"' >> $@ $(ECHO) 'set term postscript enhanced $(GNUPLOT_PS_COLOR)' >> $@ $(ECHO) 'set output "$(HOST)-avg.ps"' >> $@ $(ECHO) '$(GNUPLOTFILEINFO)' >> $@ $(ECHO) 'replot' >> $@ $(HOST)-avg3.gnuplot: $(HOST)-avg.gnuplot grep -v -E '0:[34]:xtic' $< | sed -e 's/"crx"/"create"/g;s/"wrx"/"write"/g;s/"rdx"/"read"/g;/set output/s/-avg\./-avg3./g' > $@ -include iostat-plot.mk stxxl-1.3.1/misc/icpc.supp0000644000175000017500000000036511034373030015272 0ustar andreasandreas{ icpc/openmp/libguide/sched_setaffinity/null_ptr_arg Memcheck:Param sched_setaffinity(mask) fun:syscall fun:__kmp_affinity_determine_capable fun:__kmp_env_initialize fun:__kmp_serial_initialize fun:omp_get_max_threads } stxxl-1.3.1/misc/remove-unless0000755000175000017500000000025011202775124016175 0ustar andreasandreas#!/bin/sh test $# = 3 || exit 1 file="$1" bn=`dirname "$file"`/`basename "$1" "$2"` predep="$bn$3" if [ ! -e "$predep" ]; then echo "rm -f $file" rm -f "$file" fi stxxl-1.3.1/misc/fileheader.txt0000644000175000017500000000075111024224060016270 0ustar andreasandreas/*************************************************************************** * PATH/TO/FILE.EXT * * (optional) short description * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 200X Joe XXL Coder * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ stxxl-1.3.1/misc/run-all-tests-windows.bat0000755000175000017500000000751111536140476020355 0ustar andreasandreas:: ########################################################################### :: misc\run-all-tests-windows.bat :: :: Part of the STXXL. See http://stxxl.sourceforge.net :: :: Copyright (C) 2010 Johannes Singler :: :: Distributed under the Boost Software License, Version 1.0. :: (See accompanying file LICENSE_1_0.txt or copy at :: http://www.boost.org\LICENSE_1_0.txt) :: ########################################################################### @echo on set STXXL_TMPDIR=. common\stxxl_info common\test_random common\test_manyunits common\test_globals io\gen_file "%STXXL_TMPDIR%\in" utils\createdisks 1024 "%STXXL_TMPDIR%\testdiskx" "%STXXL_TMPDIR%\testdisky" utils\createdisks 1000 "%STXXL_TMPDIR%\testdiskx" "%STXXL_TMPDIR%\testdisky" utils\log2 utils\pq_param io\benchmark_disks 0 2 32 "%STXXL_TMPDIR%\testdiskx" "%STXXL_TMPDIR%\testdisky" io\flushbuffers 2 "%STXXL_TMPDIR%\testdiskx" "%STXXL_TMPDIR%\testdisky" io\test_io "%STXXL_TMPDIR%" io\test_cancel syscall "%STXXL_TMPDIR%\testdiskx" io\test_cancel fileperblock_syscall "%STXXL_TMPDIR%\testdiskx" io\test_cancel boostfd "%STXXL_TMPDIR%\testdiskx" io\test_cancel fileperblock_boostfd "%STXXL_TMPDIR%\testdiskx" io\test_cancel memory "%STXXL_TMPDIR%\testdiskx" io\test_cancel wbtl "%STXXL_TMPDIR%\testdiskx" io\test_io_sizes wincall "%STXXL_TMPDIR%\out" 5368709120 io\test_io_sizes syscall "%STXXL_TMPDIR%\out" 5368709120 io\test_io_sizes boostfd "%STXXL_TMPDIR%\out" 5368709120 ::io\benchmark_disk_and_flash 0 2 "%STXXL_TMPDIR%\testdiskx" "%STXXL_TMPDIR%\testdisky" io\benchmark_configured_disks 2 128 io\benchmark_random_block_access 2048 1024 1000000 i io\benchmark_random_block_access 2048 128 1000000 r io\benchmark_random_block_access 2048 128 1000000 w io\iobench_scatter_in_place 100 10 4096 "%STXXL_TMPDIR%\out" io\verify_disks 123456 0 2 w "%STXXL_TMPDIR%\out" io\verify_disks 123456 0 2 r "%STXXL_TMPDIR%\out" mng\test_block_alloc_strategy mng\test_buf_streams mng\test_mng mng\test_mng1 mng\test_prefetch_pool mng\test_write_pool mng\test_pool_pair mng\test_read_write_pool mng\test_mng_recursive_alloc mng\test_aligned containers\bench_pqueue containers\copy_file "%STXXL_TMPDIR%\in" "%STXXL_TMPDIR%\out" containers\monotonic_pq 800 1 containers\pq_benchmark 1 1000000 containers\pq_benchmark 2 1000000 containers\stack_benchmark 1 1073741824 containers\stack_benchmark 2 1073741824 containers\stack_benchmark 3 1073741824 containers\stack_benchmark 4 1073741824 containers\test_deque 33333333 containers\test_ext_merger containers\test_ext_merger2 containers\test_iterators containers\test_many_stacks 42 containers\test_migr_stack containers\test_pqueue containers\test_queue containers\test_stack 1024 containers\test_vector containers\test_vector_export containers\write_vector "%STXXL_TMPDIR%\in" "%STXXL_TMPDIR%\out" containers\write_vector2 "%STXXL_TMPDIR%\in" "%STXXL_TMPDIR%\out" containers\benchmark_naive_matrix containers\test_map 32 containers\test_map_random 2000 containers\btree\test_btree 10000 containers\btree\test_btree 100000 containers\btree\test_btree 1000000 containers\btree\test_const_scan 10000 containers\btree\test_const_scan 100000 containers\btree\test_const_scan 1000000 containers\btree\test_corr_insert_erase 14 containers\btree\test_corr_insert_find 14 containers\btree\test_corr_insert_scan 14 algo\sort_file generate "%STXXL_TMPDIR%\sort_file.dat" algo\sort_file sort "%STXXL_TMPDIR%\sort_file.dat" algo\sort_file generate "%STXXL_TMPDIR%\sort_file.dat" algo\sort_file ksort "%STXXL_TMPDIR%\sort_file.dat" algo\sort_file generate "%STXXL_TMPDIR%\sort_file.dat" algo\sort_file stable_sort "%STXXL_TMPDIR%\sort_file.dat" algo\test_asch 3 100 1000 42 algo\test_ksort algo\test_random_shuffle algo\test_scan algo\test_sort algo\test_bad_cmp stream\test_push_sort stream\test_sorted_runs stream\test_stream stream\test_stream1 stream\test_transpose stream\test_loop 100 -v stxxl-1.3.1/misc/diskbench-avgdat.sh0000755000175000017500000000123111264072265017204 0ustar andreasandreas#!/bin/sh get_write() { x=`grep "# Average" $1 2>/dev/null | awk '{ print $8 }'` test -n "$x" || x=U test "$x" = "nan" && x=U test "$x" = "0.000" && x=U echo "$x" } get_read() { x=`grep "# Average" $1 2>/dev/null | awk '{ print $15 }'` test -n "$x" || x=U test "$x" = "nan" && x=U test "$x" = "0.000" && x=U echo "$x" } echo "# bs crx wr rd wrx rdx" for mb in "$@" do size=`echo $mb | sed -e 's/^0003/2.5/;s/^0012/12.5/;s/^0*//;s/\([kKMGT]\)B/\1iB/;s/MiB$//'` crx=`get_write $mb/*.crx.log` wr=`get_write $mb/*.wr.log` rd=`get_read $mb/*.wr.log` wrx=`get_write $mb/*.wrx.log` rdx=`get_read $mb/*.rdx.log` echo "$size $crx $wr $rd $wrx $rdx" done stxxl-1.3.1/misc/uncrustify.cfg0000644000175000017500000017142011520262313016341 0ustar andreasandreas# Uncrustify 0.57 # # General options # # The type of line endings newlines = auto # auto/lf/crlf/cr # The original size of tabs in the input input_tab_size = 8 # number # The size of tabs in the output (only used if align_with_tabs=true) output_tab_size = 8 # number # The ASCII value of the string escape char, usually 92 (\) or 94 (^). (Pawn) string_escape_char = 92 # number # Alternate string escape char for Pawn. Only works right before the quote char. string_escape_char2 = 0 # number # Allow interpreting '>=' and '>>=' as part of a template in 'void f(list>=val);'. # If true (default), 'assert(x<0 && y>=3)' will be broken. # Improvements to template detection may make this option obsolete. tok_split_gte = true # false/true # # Indenting # # The number of columns to indent per level. # Usually 2, 3, 4, or 8. indent_columns = 4 # number # The continuation indent. If non-zero, this overrides the indent of '(' and '=' continuation indents. # For FreeBSD, this is set to 4. indent_continue = 0 # number # How to use tabs when indenting code # 0=spaces only # 1=indent with tabs to brace level, align with spaces # 2=indent and align with tabs, using spaces when not on a tabstop indent_with_tabs = 0 # number # Comments that are not a brace level are indented with tabs on a tabstop. # Requires indent_with_tabs=2. If false, will use spaces. indent_cmt_with_tabs = false # false/true # Whether to indent strings broken by '\' so that they line up indent_align_string = false # false/true # The number of spaces to indent multi-line XML strings. # Requires indent_align_string=True indent_xml_string = 0 # number # Spaces to indent '{' from level indent_brace = 0 # number # Whether braces are indented to the body level indent_braces = false # false/true # Disabled indenting function braces if indent_braces is true indent_braces_no_func = false # false/true # Disabled indenting class braces if indent_braces is true indent_braces_no_class = false # false/true # Disabled indenting struct braces if indent_braces is true indent_braces_no_struct = false # false/true # Indent based on the size of the brace parent, i.e. 'if' => 3 spaces, 'for' => 4 spaces, etc. indent_brace_parent = false # false/true # Whether the 'namespace' body is indented indent_namespace = true # false/true # The number of spaces to indent a namespace block indent_namespace_level = 0 # number # If the body of the namespace is longer than this number, it won't be indented. # Requires indent_namespace=true. Default=0 (no limit) indent_namespace_limit = 0 # number # Whether the 'extern "C"' body is indented indent_extern = false # false/true # Whether the 'class' body is indented indent_class = true # false/true # Whether to indent the stuff after a leading class colon indent_class_colon = true # false/true # False=treat 'else\nif' as 'else if' for indenting purposes # True=indent the 'if' one level indent_else_if = false # false/true # Amount to indent variable declarations after a open brace. neg=relative, pos=absolute indent_var_def_blk = 0 # number # Indent continued variable declarations instead of aligning. indent_var_def_cont = true # false/true # True: indent continued function call parameters one indent level # False: align parameters under the open paren indent_func_call_param = false # false/true # Same as indent_func_call_param, but for function defs indent_func_def_param = false # false/true # Same as indent_func_call_param, but for function protos indent_func_proto_param = false # false/true # Same as indent_func_call_param, but for class declarations indent_func_class_param = false # false/true # Same as indent_func_call_param, but for class variable constructors indent_func_ctor_var_param = false # false/true # Same as indent_func_call_param, but for templates indent_template_param = false # false/true # Double the indent for indent_func_xxx_param options indent_func_param_double = false # false/true # Indentation column for standalone 'const' function decl/proto qualifier indent_func_const = 0 # number # Indentation column for standalone 'throw' function decl/proto qualifier indent_func_throw = 0 # number # The number of spaces to indent a continued '->' or '.' # Usually set to 0, 1, or indent_columns. indent_member = 0 # number # Spaces to indent single line ('//') comments on lines before code indent_sing_line_comments = 0 # number # If set, will indent trailing single line ('//') comments relative # to the code instead of trying to keep the same absolute column indent_relative_single_line_comments = false # false/true # Spaces to indent 'case' from 'switch' # Usually 0 or indent_columns. indent_switch_case = 0 # number # Spaces to shift the 'case' line, without affecting any other lines # Usually 0. indent_case_shift = 0 # number # Spaces to indent '{' from 'case'. # By default, the brace will appear under the 'c' in case. # Usually set to 0 or indent_columns. indent_case_brace = 0 # number # Whether to indent comments found in first column indent_col1_comment = false # false/true # How to indent goto labels # >0 : absolute column where 1 is the leftmost column # <=0 : subtract from brace indent indent_label = 1 # number # Same as indent_label, but for access specifiers that are followed by a colon indent_access_spec = -indent_columns # number # Indent the code after an access specifier by one level. # If set, this option forces 'indent_access_spec=0' indent_access_spec_body = false # false/true # If an open paren is followed by a newline, indent the next line so that it lines up after the open paren (not recommended) indent_paren_nl = false # false/true # Controls the indent of a close paren after a newline. # 0: Indent to body level # 1: Align under the open paren # 2: Indent to the brace level indent_paren_close = 0 # number # Controls the indent of a comma when inside a paren.If TRUE, aligns under the open paren indent_comma_paren = false # false/true # Controls the indent of a BOOL operator when inside a paren.If TRUE, aligns under the open paren indent_bool_paren = false # false/true # If 'indent_bool_paren' is true, controls the indent of the first expression. If TRUE, aligns the first expression to the following ones indent_first_bool_expr = false # false/true # If an open square is followed by a newline, indent the next line so that it lines up after the open square (not recommended) indent_square_nl = false # false/true # Don't change the relative indent of ESQL/C 'EXEC SQL' bodies indent_preserve_sql = false # false/true # Align continued statements at the '='. Default=True # If FALSE or the '=' is followed by a newline, the next line is indent one tab. indent_align_assign = true # false/true # # Spacing options # # Add or remove space around arithmetic operator '+', '-', '/', '*', etc sp_arith = force # ignore/add/remove/force # Add or remove space around assignment operator '=', '+=', etc sp_assign = force # ignore/add/remove/force # Add or remove space around assignment operator '=' in a prototype sp_assign_default = force # ignore/add/remove/force # Add or remove space before assignment operator '=', '+=', etc. Overrides sp_assign. sp_before_assign = force # ignore/add/remove/force # Add or remove space after assignment operator '=', '+=', etc. Overrides sp_assign. sp_after_assign = force # ignore/add/remove/force # Add or remove space around assignment '=' in enum sp_enum_assign = force # ignore/add/remove/force # Add or remove space before assignment '=' in enum. Overrides sp_enum_assign. sp_enum_before_assign = force # ignore/add/remove/force # Add or remove space after assignment '=' in enum. Overrides sp_enum_assign. sp_enum_after_assign = force # ignore/add/remove/force # Add or remove space around preprocessor '##' concatenation operator. Default=Add sp_pp_concat = force # ignore/add/remove/force # Add or remove space after preprocessor '#' stringify operator. Also affects the '#@' charizing operator. Default=Add sp_pp_stringify = ignore # ignore/add/remove/force # Add or remove space around boolean operators '&&' and '||' sp_bool = force # ignore/add/remove/force # Add or remove space around compare operator '<', '>', '==', etc sp_compare = force # ignore/add/remove/force # Add or remove space inside '(' and ')' sp_inside_paren = remove # ignore/add/remove/force # Add or remove space between nested parens sp_paren_paren = remove # ignore/add/remove/force # Whether to balance spaces inside nested parens sp_balance_nested_parens = false # false/true # Add or remove space between ')' and '{' sp_paren_brace = force # ignore/add/remove/force # Add or remove space before pointer star '*' sp_before_ptr_star = force # ignore/add/remove/force # Add or remove space before pointer star '*' that isn't followed by a variable name # If set to 'ignore', sp_before_ptr_star is used instead. sp_before_unnamed_ptr_star = ignore # ignore/add/remove/force # Add or remove space between pointer stars '*' sp_between_ptr_star = remove # ignore/add/remove/force # Add or remove space after pointer star '*', if followed by a word. sp_after_ptr_star = force # ignore/add/remove/force # Add or remove space after a pointer star '*', if followed by a func proto/def. sp_after_ptr_star_func = force # ignore/add/remove/force # Add or remove space before a pointer star '*', if followed by a func proto/def. sp_before_ptr_star_func = force # ignore/add/remove/force # Add or remove space before a reference sign '&' sp_before_byref = force # ignore/add/remove/force # Add or remove space before a reference sign '&' that isn't followed by a variable name # If set to 'ignore', sp_before_byref is used instead. sp_before_unnamed_byref = ignore # ignore/add/remove/force # Add or remove space after reference sign '&', if followed by a word. sp_after_byref = force # ignore/add/remove/force # Add or remove space after a reference sign '&', if followed by a func proto/def. sp_after_byref_func = force # ignore/add/remove/force # Add or remove space before a reference sign '&', if followed by a func proto/def. sp_before_byref_func = force # ignore/add/remove/force # Add or remove space between type and word. Default=Force sp_after_type = force # ignore/add/remove/force # Add or remove space in 'template <' vs 'template<'. # If set to ignore, sp_before_angle is used. sp_template_angle = force # ignore/add/remove/force # Add or remove space before '<>' sp_before_angle = remove # ignore/add/remove/force # Add or remove space inside '<' and '>' sp_inside_angle = remove # ignore/add/remove/force # Add or remove space after '<>' sp_after_angle = remove # ignore/add/remove/force # Add or remove space between '<>' and '(' as found in 'new List();' sp_angle_paren = remove # ignore/add/remove/force # Add or remove space between '<>' and a word as in 'List m;' sp_angle_word = force # ignore/add/remove/force # Add or remove space between '>' and '>' in '>>' (template stuff C++/C# only). Default=Add sp_angle_shift = force # ignore/add/remove/force # Add or remove space before '(' of 'if', 'for', 'switch', and 'while' sp_before_sparen = force # ignore/add/remove/force # Add or remove space inside if-condition '(' and ')' sp_inside_sparen = remove # ignore/add/remove/force # Add or remove space before if-condition ')'. Overrides sp_inside_sparen. sp_inside_sparen_close = ignore # ignore/add/remove/force # Add or remove space after ')' of 'if', 'for', 'switch', and 'while' sp_after_sparen = force # ignore/add/remove/force # Add or remove space between ')' and '{' of 'if', 'for', 'switch', and 'while' sp_sparen_brace = force # ignore/add/remove/force # Add or remove space between 'invariant' and '(' in the D language. sp_invariant_paren = ignore # ignore/add/remove/force # Add or remove space after the ')' in 'invariant (C) c' in the D language. sp_after_invariant_paren = ignore # ignore/add/remove/force # Add or remove space before empty statement ';' on 'if', 'for' and 'while' sp_special_semi = force # ignore/add/remove/force # Add or remove space before ';'. Default=Remove sp_before_semi = remove # ignore/add/remove/force # Add or remove space before ';' in non-empty 'for' statements sp_before_semi_for = remove # ignore/add/remove/force # Add or remove space before a semicolon of an empty part of a for statement. sp_before_semi_for_empty = force # ignore/add/remove/force # Add or remove space after ';', except when followed by a comment. Default=Add sp_after_semi = add # ignore/add/remove/force # Add or remove space after ';' in non-empty 'for' statements. Default=Force sp_after_semi_for = force # ignore/add/remove/force # Add or remove space after the final semicolon of an empty part of a for statement: for ( ; ; ). sp_after_semi_for_empty = force # ignore/add/remove/force # Add or remove space before '[' (except '[]') sp_before_square = remove # ignore/add/remove/force # Add or remove space before '[]' sp_before_squares = remove # ignore/add/remove/force # Add or remove space inside '[' and ']' sp_inside_square = remove # ignore/add/remove/force # Add or remove space after ',' sp_after_comma = force # ignore/add/remove/force # Add or remove space before ',' sp_before_comma = remove # ignore/add/remove/force # Add or remove space between an open paren and comma: '(,' vs '( ,' sp_paren_comma = force # ignore/add/remove/force # Add or remove space before the variadic '...' when preceded by a non-punctuator sp_before_ellipsis = ignore # ignore/add/remove/force # Add or remove space after class ':' sp_after_class_colon = force # ignore/add/remove/force # Add or remove space before class ':' sp_before_class_colon = force # ignore/add/remove/force # Add or remove space before case ':'. Default=Remove sp_before_case_colon = remove # ignore/add/remove/force # Add or remove space between 'operator' and operator sign sp_after_operator = force # ignore/add/remove/force # Add or remove space between the operator symbol and the open paren, as in 'operator ++(' sp_after_operator_sym = force # ignore/add/remove/force # Add or remove space after C/D cast, i.e. 'cast(int)a' vs 'cast(int) a' or '(int)a' vs '(int) a' sp_after_cast = remove # ignore/add/remove/force # Add or remove spaces inside cast parens sp_inside_paren_cast = remove # ignore/add/remove/force # Add or remove space between the type and open paren in a C++ cast, i.e. 'int(exp)' vs 'int (exp)' sp_cpp_cast_paren = remove # ignore/add/remove/force # Add or remove space between 'sizeof' and '(' sp_sizeof_paren = remove # ignore/add/remove/force # Add or remove space after the tag keyword (Pawn) sp_after_tag = ignore # ignore/add/remove/force # Add or remove space inside enum '{' and '}' sp_inside_braces_enum = force # ignore/add/remove/force # Add or remove space inside struct/union '{' and '}' sp_inside_braces_struct = force # ignore/add/remove/force # Add or remove space inside '{' and '}' sp_inside_braces = force # ignore/add/remove/force # Add or remove space inside '{}' sp_inside_braces_empty = force # ignore/add/remove/force # Add or remove space between return type and function name # A minimum of 1 is forced except for pointer return types. sp_type_func = force # ignore/add/remove/force # Add or remove space between function name and '(' on function declaration sp_func_proto_paren = remove # ignore/add/remove/force # Add or remove space between function name and '(' on function definition sp_func_def_paren = remove # ignore/add/remove/force # Add or remove space inside empty function '()' sp_inside_fparens = remove # ignore/add/remove/force # Add or remove space inside function '(' and ')' sp_inside_fparen = remove # ignore/add/remove/force # Add or remove space between ']' and '(' when part of a function call. sp_square_fparen = remove # ignore/add/remove/force # Add or remove space between ')' and '{' of function sp_fparen_brace = force # ignore/add/remove/force # Add or remove space between function name and '(' on function calls sp_func_call_paren = remove # ignore/add/remove/force # Add or remove space between function name and '()' on function calls without parameters. # If set to 'ignore' (the default), sp_func_call_paren is used. sp_func_call_paren_empty = ignore # ignore/add/remove/force # Add or remove space between the user function name and '(' on function calls # You need to set a keyword to be a user function, like this: 'set func_call_user _' in the config file. sp_func_call_user_paren = remove # ignore/add/remove/force # Add or remove space between a constructor/destructor and the open paren sp_func_class_paren = remove # ignore/add/remove/force # Add or remove space between 'return' and '(' sp_return_paren = force # ignore/add/remove/force # Add or remove space between '__attribute__' and '(' sp_attribute_paren = force # ignore/add/remove/force # Add or remove space between 'defined' and '(' in '#if defined (FOO)' sp_defined_paren = ignore # ignore/add/remove/force # Add or remove space between 'throw' and '(' in 'throw (something)' sp_throw_paren = force # ignore/add/remove/force # Add or remove space between 'catch' and '(' in 'catch (something) { }' # If set to ignore, sp_before_sparen is used. sp_catch_paren = force # ignore/add/remove/force # Add or remove space between 'version' and '(' in 'version (something) { }' (D language) # If set to ignore, sp_before_sparen is used. sp_version_paren = ignore # ignore/add/remove/force # Add or remove space between 'scope' and '(' in 'scope (something) { }' (D language) # If set to ignore, sp_before_sparen is used. sp_scope_paren = ignore # ignore/add/remove/force # Add or remove space between macro and value sp_macro = ignore # ignore/add/remove/force # Add or remove space between macro function ')' and value sp_macro_func = ignore # ignore/add/remove/force # Add or remove space between 'else' and '{' if on the same line sp_else_brace = force # ignore/add/remove/force # Add or remove space between '}' and 'else' if on the same line sp_brace_else = force # ignore/add/remove/force # Add or remove space between '}' and the name of a typedef on the same line sp_brace_typedef = force # ignore/add/remove/force # Add or remove space between 'catch' and '{' if on the same line sp_catch_brace = force # ignore/add/remove/force # Add or remove space between '}' and 'catch' if on the same line sp_brace_catch = force # ignore/add/remove/force # Add or remove space between 'finally' and '{' if on the same line sp_finally_brace = force # ignore/add/remove/force # Add or remove space between '}' and 'finally' if on the same line sp_brace_finally = force # ignore/add/remove/force # Add or remove space between 'try' and '{' if on the same line sp_try_brace = force # ignore/add/remove/force # Add or remove space between get/set and '{' if on the same line sp_getset_brace = ignore # ignore/add/remove/force # Add or remove space before the '::' operator sp_before_dc = remove # ignore/add/remove/force # Add or remove space after the '::' operator sp_after_dc = remove # ignore/add/remove/force # Add or remove around the D named array initializer ':' operator sp_d_array_colon = ignore # ignore/add/remove/force # Add or remove space after the '!' (not) operator. Default=Remove sp_not = ignore # ignore/add/remove/force # Add or remove space after the '~' (invert) operator. Default=Remove sp_inv = remove # ignore/add/remove/force # Add or remove space after the '&' (address-of) operator. Default=Remove # This does not affect the spacing after a '&' that is part of a type. sp_addr = remove # ignore/add/remove/force # Add or remove space around the '.' or '->' operators. Default=Remove sp_member = remove # ignore/add/remove/force # Add or remove space after the '*' (dereference) operator. Default=Remove # This does not affect the spacing after a '*' that is part of a type. sp_deref = remove # ignore/add/remove/force # Add or remove space after '+' or '-', as in 'x = -5' or 'y = +7'. Default=Remove sp_sign = remove # ignore/add/remove/force # Add or remove space before or after '++' and '--', as in '(--x)' or 'y++;'. Default=Remove sp_incdec = remove # ignore/add/remove/force # Add or remove space before a backslash-newline at the end of a line. Default=Add sp_before_nl_cont = force # ignore/add/remove/force # Add or remove space after the scope '+' or '-', as in '-(void) foo;' or '+(int) bar;' sp_after_oc_scope = ignore # ignore/add/remove/force # Add or remove space after the colon in message specs # '-(int) f:(int) x;' vs '-(int) f: (int) x;' sp_after_oc_colon = ignore # ignore/add/remove/force # Add or remove space before the colon in message specs # '-(int) f: (int) x;' vs '-(int) f : (int) x;' sp_before_oc_colon = ignore # ignore/add/remove/force # Add or remove space after the colon in message specs # '[object setValue:1];' vs '[object setValue: 1];' sp_after_send_oc_colon = ignore # ignore/add/remove/force # Add or remove space before the colon in message specs # '[object setValue:1];' vs '[object setValue :1];' sp_before_send_oc_colon = ignore # ignore/add/remove/force # Add or remove space after the (type) in message specs # '-(int)f: (int) x;' vs '-(int)f: (int)x;' sp_after_oc_type = ignore # ignore/add/remove/force # Add or remove space after the first (type) in message specs # '-(int) f:(int)x;' vs '-(int)f:(int)x;' sp_after_oc_return_type = ignore # ignore/add/remove/force # Add or remove space between '@selector' and '(' # '@selector(msgName)' vs '@selector (msgName)' # Also applies to @protocol() constructs sp_after_oc_at_sel = ignore # ignore/add/remove/force # Add or remove space between '@selector(x)' and the following word # '@selector(foo) a:' vs '@selector(foo)a:' sp_after_oc_at_sel_parens = ignore # ignore/add/remove/force # Add or remove space inside '@selector' parens # '@selector(foo)' vs '@selector( foo )' # Also applies to @protocol() constructs sp_inside_oc_at_sel_parens = ignore # ignore/add/remove/force # Add or remove space before a block pointer caret # '^int (int arg){...}' vs. ' ^int (int arg){...}' sp_before_oc_block_caret = ignore # ignore/add/remove/force # Add or remove space after a block pointer caret # '^int (int arg){...}' vs. '^ int (int arg){...}' sp_after_oc_block_caret = ignore # ignore/add/remove/force # Add or remove space around the ':' in 'b ? t : f' sp_cond_colon = force # ignore/add/remove/force # Add or remove space around the '?' in 'b ? t : f' sp_cond_question = force # ignore/add/remove/force # Fix the spacing between 'case' and the label. Only 'ignore' and 'force' make sense here. sp_case_label = force # ignore/add/remove/force # Control the space around the D '..' operator. sp_range = ignore # ignore/add/remove/force # Control the space after the opening of a C++ comment '// A' vs '//A' sp_cmt_cpp_start = ignore # ignore/add/remove/force # Controls the spaces between #else or #endif and a trailing comment sp_endif_cmt = ignore # ignore/add/remove/force # # Code alignment (not left column spaces/tabs) # # Whether to keep non-indenting tabs align_keep_tabs = false # false/true # Whether to use tabs for aligning align_with_tabs = false # false/true # Whether to bump out to the next tab when aligning align_on_tabstop = false # false/true # Whether to left-align numbers align_number_left = false # false/true # Align variable definitions in prototypes and functions align_func_params = false # false/true # Align parameters in single-line functions that have the same name. # The function names must already be aligned with each other. align_same_func_call_params = false # false/true # The span for aligning variable definitions (0=don't align) align_var_def_span = 0 # number # How to align the star in variable definitions. # 0=Part of the type 'void * foo;' # 1=Part of the variable 'void *foo;' # 2=Dangling 'void *foo;' align_var_def_star_style = 1 # number # How to align the '&' in variable definitions. # 0=Part of the type # 1=Part of the variable # 2=Dangling align_var_def_amp_style = 0 # number # The threshold for aligning variable definitions (0=no limit) align_var_def_thresh = 0 # number # The gap for aligning variable definitions align_var_def_gap = 0 # number # Whether to align the colon in struct bit fields align_var_def_colon = false # false/true # Whether to align any attribute after the variable name align_var_def_attribute = false # false/true # Whether to align inline struct/enum/union variable definitions align_var_def_inline = false # false/true # The span for aligning on '=' in assignments (0=don't align) align_assign_span = 0 # number # The threshold for aligning on '=' in assignments (0=no limit) align_assign_thresh = 0 # number # The span for aligning on '=' in enums (0=don't align) align_enum_equ_span = 0 # number # The threshold for aligning on '=' in enums (0=no limit) align_enum_equ_thresh = 0 # number # The span for aligning struct/union (0=don't align) align_var_struct_span = 0 # number # The threshold for aligning struct/union member definitions (0=no limit) align_var_struct_thresh = 0 # number # The gap for aligning struct/union member definitions align_var_struct_gap = 0 # number # The span for aligning struct initializer values (0=don't align) align_struct_init_span = 0 # number # The minimum space between the type and the synonym of a typedef align_typedef_gap = 0 # number # The span for aligning single-line typedefs (0=don't align) align_typedef_span = 0 # number # How to align typedef'd functions with other typedefs # 0: Don't mix them at all # 1: align the open paren with the types # 2: align the function type name with the other type names align_typedef_func = 0 # number # Controls the positioning of the '*' in typedefs. Just try it. # 0: Align on typedef type, ignore '*' # 1: The '*' is part of type name: typedef int *pint; # 2: The '*' is part of the type, but dangling: typedef int *pint; align_typedef_star_style = 0 # number # Controls the positioning of the '&' in typedefs. Just try it. # 0: Align on typedef type, ignore '&' # 1: The '&' is part of type name: typedef int &pint; # 2: The '&' is part of the type, but dangling: typedef int &pint; align_typedef_amp_style = 0 # number # The span for aligning comments that end lines (0=don't align) align_right_cmt_span = 5 # number # If aligning comments, mix with comments after '}' and #endif with less than 3 spaces before the comment align_right_cmt_mix = false # false/true # If a trailing comment is more than this number of columns away from the text it follows, # it will qualify for being aligned. This has to be > 0 to do anything. align_right_cmt_gap = 0 # number # Align trailing comment at or beyond column N; 'pulls in' comments as a bonus side effect (0=ignore) align_right_cmt_at_col = 0 # number # The span for aligning function prototypes (0=don't align) align_func_proto_span = 0 # number # Minimum gap between the return type and the function name. align_func_proto_gap = 0 # number # Align function protos on the 'operator' keyword instead of what follows align_on_operator = false # false/true # Whether to mix aligning prototype and variable declarations. # If true, align_var_def_XXX options are used instead of align_func_proto_XXX options. align_mix_var_proto = false # false/true # Align single-line functions with function prototypes, uses align_func_proto_span align_single_line_func = false # false/true # Aligning the open brace of single-line functions. # Requires align_single_line_func=true, uses align_func_proto_span align_single_line_brace = false # false/true # Gap for align_single_line_brace. align_single_line_brace_gap = 0 # number # The span for aligning ObjC msg spec (0=don't align) align_oc_msg_spec_span = 0 # number # Whether to align macros wrapped with a backslash and a newline. # This will not work right if the macro contains a multi-line comment. align_nl_cont = false # false/true # The minimum space between label and value of a preprocessor define align_pp_define_gap = 0 # number # The span for aligning on '#define' bodies (0=don't align) align_pp_define_span = 0 # number # Align lines that start with '<<' with previous '<<'. Default=true align_left_shift = true # false/true # Span for aligning parameters in an Obj-C message call on the ':' (0=don't align) align_oc_msg_colon_span = 0 # number # Aligning parameters in an Obj-C '+' or '-' declaration on the ':' align_oc_decl_colon = false # false/true # # Newline adding and removing options # # Whether to collapse empty blocks between '{' and '}' nl_collapse_empty_body = true # false/true # Don't split one-line braced assignments - 'foo_t f = { 1, 2 };' nl_assign_leave_one_liners = true # false/true # Don't split one-line braced statements inside a class xx { } body nl_class_leave_one_liners = true # false/true # Don't split one-line enums: 'enum foo { BAR = 15 };' nl_enum_leave_one_liners = true # false/true # Don't split one-line get or set functions nl_getset_leave_one_liners = true # false/true # Don't split one-line function definitions - 'int foo() { return 0; }' nl_func_leave_one_liners = false # false/true # Don't split one-line if/else statements - 'if(a) b++;' nl_if_leave_one_liners = false # false/true # Add or remove newlines at the start of the file nl_start_of_file = remove # ignore/add/remove/force # The number of newlines at the start of the file (only used if nl_start_of_file is 'add' or 'force' nl_start_of_file_min = 0 # number # Add or remove newline at the end of the file nl_end_of_file = force # ignore/add/remove/force # The number of newlines at the end of the file (only used if nl_end_of_file is 'add' or 'force') nl_end_of_file_min = 1 # number # Add or remove newline between '=' and '{' nl_assign_brace = ignore # ignore/add/remove/force # Add or remove newline between '=' and '[' (D only) nl_assign_square = ignore # ignore/add/remove/force # Add or remove newline after '= [' (D only). Will also affect the newline before the ']' nl_after_square_assign = ignore # ignore/add/remove/force # The number of blank lines after a block of variable definitions nl_func_var_def_blk = 0 # number # Add or remove newline between a function call's ')' and '{', as in: # list_for_each(item, &list) { } nl_fcall_brace = ignore # ignore/add/remove/force # Add or remove newline between 'enum' and '{' nl_enum_brace = ignore # ignore/add/remove/force # Add or remove newline between 'struct and '{' nl_struct_brace = ignore # ignore/add/remove/force # Add or remove newline between 'union' and '{' nl_union_brace = ignore # ignore/add/remove/force # Add or remove newline between 'if' and '{' nl_if_brace = ignore # ignore/add/remove/force # Add or remove newline between '}' and 'else' nl_brace_else = ignore # ignore/add/remove/force # Add or remove newline between 'else if' and '{' # If set to ignore, nl_if_brace is used instead nl_elseif_brace = ignore # ignore/add/remove/force # Add or remove newline between 'else' and '{' nl_else_brace = ignore # ignore/add/remove/force # Add or remove newline between 'else' and 'if' nl_else_if = remove # ignore/add/remove/force # Add or remove newline between '}' and 'finally' nl_brace_finally = ignore # ignore/add/remove/force # Add or remove newline between 'finally' and '{' nl_finally_brace = ignore # ignore/add/remove/force # Add or remove newline between 'try' and '{' nl_try_brace = ignore # ignore/add/remove/force # Add or remove newline between get/set and '{' nl_getset_brace = ignore # ignore/add/remove/force # Add or remove newline between 'for' and '{' nl_for_brace = ignore # ignore/add/remove/force # Add or remove newline between 'catch' and '{' nl_catch_brace = ignore # ignore/add/remove/force # Add or remove newline between '}' and 'catch' nl_brace_catch = ignore # ignore/add/remove/force # Add or remove newline between 'while' and '{' nl_while_brace = ignore # ignore/add/remove/force # Add or remove newline between 'using' and '{' nl_using_brace = ignore # ignore/add/remove/force # Add or remove newline between two open or close braces. # Due to general newline/brace handling, REMOVE may not work. nl_brace_brace = force # ignore/add/remove/force # Add or remove newline between 'do' and '{' nl_do_brace = ignore # ignore/add/remove/force # Add or remove newline between '}' and 'while' of 'do' statement nl_brace_while = ignore # ignore/add/remove/force # Add or remove newline between 'switch' and '{' nl_switch_brace = ignore # ignore/add/remove/force # Add a newline between ')' and '{' if the ')' is on a different line than the if/for/etc. # Overrides nl_for_brace, nl_if_brace, nl_switch_brace, nl_while_switch, and nl_catch_brace. nl_multi_line_cond = false # false/true # Force a newline in a define after the macro name for multi-line defines. nl_multi_line_define = false # false/true # Whether to put a newline before 'case' statement nl_before_case = false # false/true # Add or remove newline between ')' and 'throw' nl_before_throw = ignore # ignore/add/remove/force # Whether to put a newline after 'case' statement nl_after_case = false # false/true # Newline between namespace and { nl_namespace_brace = add # ignore/add/remove/force # Add or remove newline between 'template<>' and whatever follows. nl_template_class = add # ignore/add/remove/force # Add or remove newline between 'class' and '{' nl_class_brace = ignore # ignore/add/remove/force # Add or remove newline after each ',' in the constructor member initialization nl_class_init_args = ignore # ignore/add/remove/force # Add or remove newline between return type and function name in a function definition nl_func_type_name = ignore # ignore/add/remove/force # Add or remove newline between return type and function name inside a class {} # Uses nl_func_type_name or nl_func_proto_type_name if set to ignore. nl_func_type_name_class = ignore # ignore/add/remove/force # Add or remove newline between function scope and name in a definition # Controls the newline after '::' in 'void A::f() { }' nl_func_scope_name = ignore # ignore/add/remove/force # Add or remove newline between return type and function name in a prototype nl_func_proto_type_name = ignore # ignore/add/remove/force # Add or remove newline between a function name and the opening '(' nl_func_paren = ignore # ignore/add/remove/force # Add or remove newline between a function name and the opening '(' in the definition nl_func_def_paren = ignore # ignore/add/remove/force # Add or remove newline after '(' in a function declaration nl_func_decl_start = ignore # ignore/add/remove/force # Add or remove newline after '(' in a function definition nl_func_def_start = ignore # ignore/add/remove/force # Overrides nl_func_decl_start when there is only one parameter. nl_func_decl_start_single = ignore # ignore/add/remove/force # Overrides nl_func_def_start when there is only one parameter. nl_func_def_start_single = ignore # ignore/add/remove/force # Add or remove newline after each ',' in a function declaration nl_func_decl_args = ignore # ignore/add/remove/force # Add or remove newline after each ',' in a function definition nl_func_def_args = ignore # ignore/add/remove/force # Add or remove newline before the ')' in a function declaration nl_func_decl_end = ignore # ignore/add/remove/force # Add or remove newline before the ')' in a function definition nl_func_def_end = ignore # ignore/add/remove/force # Overrides nl_func_decl_end when there is only one parameter. nl_func_decl_end_single = ignore # ignore/add/remove/force # Overrides nl_func_def_end when there is only one parameter. nl_func_def_end_single = ignore # ignore/add/remove/force # Add or remove newline between '()' in a function declaration. nl_func_decl_empty = remove # ignore/add/remove/force # Add or remove newline between '()' in a function definition. nl_func_def_empty = remove # ignore/add/remove/force # Add or remove newline between function signature and '{' nl_fdef_brace = force # ignore/add/remove/force # Whether to put a newline after 'return' statement nl_after_return = false # false/true # Add or remove a newline between the return keyword and return expression. nl_return_expr = remove # ignore/add/remove/force # Whether to put a newline after semicolons, except in 'for' statements nl_after_semicolon = true # false/true # Whether to put a newline after brace open. # This also adds a newline before the matching brace close. nl_after_brace_open = true # false/true # If nl_after_brace_open and nl_after_brace_open_cmt are true, a newline is # placed between the open brace and a trailing single-line comment. nl_after_brace_open_cmt = false # false/true # Whether to put a newline after a virtual brace open with a non-empty body. # These occur in un-braced if/while/do/for statement bodies. nl_after_vbrace_open = false # false/true # Whether to put a newline after a virtual brace open with an empty body. # These occur in un-braced if/while/do/for statement bodies. nl_after_vbrace_open_empty = false # false/true # Whether to put a newline after a brace close. # Does not apply if followed by a necessary ';'. nl_after_brace_close = false # false/true # Whether to put a newline after a virtual brace close. # Would add a newline before return in: 'if (foo) a++; return;' nl_after_vbrace_close = false # false/true # Whether to alter newlines in '#define' macros nl_define_macro = false # false/true # Whether to not put blanks after '#ifxx', '#elxx', or before '#endif' nl_squeeze_ifdef = false # false/true # Add or remove blank line before 'if' nl_before_if = ignore # ignore/add/remove/force # Add or remove blank line after 'if' statement nl_after_if = ignore # ignore/add/remove/force # Add or remove blank line before 'for' nl_before_for = ignore # ignore/add/remove/force # Add or remove blank line after 'for' statement nl_after_for = ignore # ignore/add/remove/force # Add or remove blank line before 'while' nl_before_while = ignore # ignore/add/remove/force # Add or remove blank line after 'while' statement nl_after_while = ignore # ignore/add/remove/force # Add or remove blank line before 'switch' nl_before_switch = ignore # ignore/add/remove/force # Add or remove blank line after 'switch' statement nl_after_switch = ignore # ignore/add/remove/force # Add or remove blank line before 'do' nl_before_do = ignore # ignore/add/remove/force # Add or remove blank line after 'do/while' statement nl_after_do = ignore # ignore/add/remove/force # Whether to double-space commented-entries in struct/enum nl_ds_struct_enum_cmt = false # false/true # Whether to double-space before the close brace of a struct/union/enum # (lower priority than 'eat_blanks_before_close_brace') nl_ds_struct_enum_close_brace = false # false/true # Add or remove a newline around a class colon. # Related to pos_class_colon, nl_class_init_args, and pos_comma. nl_class_colon = ignore # ignore/add/remove/force # Change simple unbraced if statements into a one-liner # 'if(b)\n i++;' => 'if(b) i++;' nl_create_if_one_liner = false # false/true # Change simple unbraced for statements into a one-liner # 'for (i=0;i<5;i++)\n foo(i);' => 'for (i=0;i<5;i++) foo(i);' nl_create_for_one_liner = false # false/true # Change simple unbraced while statements into a one-liner # 'while (i<5)\n foo(i++);' => 'while (i<5) foo(i++);' nl_create_while_one_liner = false # false/true # # Positioning options # # The position of arithmetic operators in wrapped expressions pos_arith = ignore # ignore/lead/lead_break/lead_force/trail/trail_break/trail_force # The position of assignment in wrapped expressions. # Do not affect '=' followed by '{' pos_assign = ignore # ignore/lead/lead_break/lead_force/trail/trail_break/trail_force # The position of boolean operators in wrapped expressions pos_bool = ignore # ignore/lead/lead_break/lead_force/trail/trail_break/trail_force # The position of comparison operators in wrapped expressions pos_compare = ignore # ignore/lead/lead_break/lead_force/trail/trail_break/trail_force # The position of conditional (b ? t : f) operators in wrapped expressions pos_conditional = ignore # ignore/lead/lead_break/lead_force/trail/trail_break/trail_force # The position of the comma in wrapped expressions pos_comma = trail # ignore/lead/lead_break/lead_force/trail/trail_break/trail_force # The position of the comma in the constructor initialization list pos_class_comma = trail # ignore/lead/lead_break/lead_force/trail/trail_break/trail_force # The position of colons between constructor and member initialization pos_class_colon = ignore # ignore/lead/lead_break/lead_force/trail/trail_break/trail_force # # Line Splitting options # # Try to limit code width to N number of columns code_width = 0 # number # Whether to fully split long 'for' statements at semi-colons ls_for_split_full = true # false/true # Whether to fully split long function protos/calls at commas ls_func_split_full = true # false/true # # Blank line options # # The maximum consecutive newlines nl_max = 3 # number # The number of newlines after a function prototype, if followed by another function prototype nl_after_func_proto = 0 # number # The number of newlines after a function prototype, if not followed by another function prototype nl_after_func_proto_group = 0 # number # The number of newlines after '}' of a multi-line function body nl_after_func_body = 0 # number # The number of newlines after '}' of a single line function body nl_after_func_body_one_liner = 0 # number # The minimum number of newlines before a multi-line comment. # Doesn't apply if after a brace open or another multi-line comment. nl_before_block_comment = 0 # number # The minimum number of newlines before a single-line C comment. # Doesn't apply if after a brace open or other single-line C comments. nl_before_c_comment = 0 # number # The minimum number of newlines before a CPP comment. # Doesn't apply if after a brace open or other CPP comments. nl_before_cpp_comment = 0 # number # Whether to force a newline after a multi-line comment. nl_after_multiline_comment = false # false/true # The number of newlines before a 'private:', 'public:', 'protected:', 'signals:', or 'slots:' label. # Will not change the newline count if after a brace open. # 0 = No change. nl_before_access_spec = 2 # number # The number of newlines after a 'private:', 'public:', 'protected:', 'signals:', or 'slots:' label. # 0 = No change. nl_after_access_spec = 1 # number # The number of newlines between a function def and the function comment. # 0 = No change. nl_comment_func_def = 0 # number # The number of newlines after a try-catch-finally block that isn't followed by a brace close. # 0 = No change. nl_after_try_catch_finally = 0 # number # The number of newlines before and after a property, indexer or event decl. # 0 = No change. nl_around_cs_property = 0 # number # The number of newlines between the get/set/add/remove handlers in C#. # 0 = No change. nl_between_get_set = 0 # number # Whether to remove blank lines after '{' eat_blanks_after_open_brace = true # false/true # Whether to remove blank lines before '}' eat_blanks_before_close_brace = true # false/true # # Code modifying options (non-whitespace) # # Add or remove braces on single-line 'do' statement mod_full_brace_do = ignore # ignore/add/remove/force # Add or remove braces on single-line 'for' statement mod_full_brace_for = ignore # ignore/add/remove/force # Add or remove braces on single-line function definitions. (Pawn) mod_full_brace_function = ignore # ignore/add/remove/force # Add or remove braces on single-line 'if' statement. Will not remove the braces if they contain an 'else'. mod_full_brace_if = ignore # ignore/add/remove/force # Make all if/elseif/else statements in a chain be braced or not. Overrides mod_full_brace_if. # If any must be braced, they are all braced. If all can be unbraced, then the braces are removed. mod_full_brace_if_chain = false # false/true # Don't remove braces around statements that span N newlines mod_full_brace_nl = 0 # number # Add or remove braces on single-line 'while' statement mod_full_brace_while = ignore # ignore/add/remove/force # Add or remove braces on single-line 'using ()' statement mod_full_brace_using = ignore # ignore/add/remove/force # Add or remove unnecessary paren on 'return' statement mod_paren_on_return = ignore # ignore/add/remove/force # Whether to change optional semicolons to real semicolons mod_pawn_semicolon = false # false/true # Add parens on 'while' and 'if' statement around bools mod_full_paren_if_bool = false # false/true # Whether to remove superfluous semicolons mod_remove_extra_semicolon = true # false/true # If a function body exceeds the specified number of newlines and doesn't have a comment after # the close brace, a comment will be added. mod_add_long_function_closebrace_comment = 0 # number # If a switch body exceeds the specified number of newlines and doesn't have a comment after # the close brace, a comment will be added. mod_add_long_switch_closebrace_comment = 0 # number # If an #ifdef body exceeds the specified number of newlines and doesn't have a comment after # the #else, a comment will be added. mod_add_long_ifdef_endif_comment = 0 # number # If an #ifdef or #else body exceeds the specified number of newlines and doesn't have a comment after # the #endif, a comment will be added. mod_add_long_ifdef_else_comment = 0 # number # If TRUE, will sort consecutive single-line 'import' statements [Java, D] mod_sort_import = false # false/true # If TRUE, will sort consecutive single-line 'using' statements [C#] mod_sort_using = false # false/true # If TRUE, will sort consecutive single-line '#include' statements [C/C++] and '#import' statements [Obj-C] # This is generally a bad idea, as it may break your code. mod_sort_include = false # false/true # If TRUE, it will move a 'break' that appears after a fully braced 'case' before the close brace. mod_move_case_break = false # false/true # Will add or remove the braces around a fully braced case statement. # Will only remove the braces if there are no variable declarations in the block. mod_case_brace = ignore # ignore/add/remove/force # If TRUE, it will remove a void 'return;' that appears as the last statement in a function. mod_remove_empty_return = false # false/true # # Comment modifications # # Try to wrap comments at cmt_width columns cmt_width = 0 # number # Set the comment reflow mode (default: 0) # 0: no reflowing (apart from the line wrapping due to cmt_width) # 1: no touching at all # 2: full reflow cmt_reflow_mode = 0 # number # If false, disable all multi-line comment changes, including cmt_width. keyword substitution, and leading chars. # Default is true. cmt_indent_multi = false # false/true # Whether to group c-comments that look like they are in a block cmt_c_group = false # false/true # Whether to put an empty '/*' on the first line of the combined c-comment cmt_c_nl_start = false # false/true # Whether to put a newline before the closing '*/' of the combined c-comment cmt_c_nl_end = false # false/true # Whether to group cpp-comments that look like they are in a block cmt_cpp_group = false # false/true # Whether to put an empty '/*' on the first line of the combined cpp-comment cmt_cpp_nl_start = false # false/true # Whether to put a newline before the closing '*/' of the combined cpp-comment cmt_cpp_nl_end = false # false/true # Whether to change cpp-comments into c-comments cmt_cpp_to_c = false # false/true # Whether to put a star on subsequent comment lines cmt_star_cont = false # false/true # The number of spaces to insert at the start of subsequent comment lines cmt_sp_before_star_cont = 0 # number # The number of spaces to insert after the star on subsequent comment lines cmt_sp_after_star_cont = 0 # number # For multi-line comments with a '*' lead, remove leading spaces if the first and last lines of # the comment are the same length. Default=True cmt_multi_check_last = true # false/true # The filename that contains text to insert at the head of a file if the file doesn't start with a C/C++ comment. # Will substitute $(filename) with the current file's name. cmt_insert_file_header = "" # string # The filename that contains text to insert at the end of a file if the file doesn't end with a C/C++ comment. # Will substitute $(filename) with the current file's name. cmt_insert_file_footer = "" # string # The filename that contains text to insert before a function implementation if the function isn't preceded with a C/C++ comment. # Will substitute $(function) with the function name and $(javaparam) with the javadoc @param and @return stuff. # Will also substitute $(fclass) with the class name: void CFoo::Bar() { ... } cmt_insert_func_header = "" # string # The filename that contains text to insert before a class if the class isn't preceded with a C/C++ comment. # Will substitute $(class) with the class name. cmt_insert_class_header = "" # string # If a preprocessor is encountered when stepping backwards from a function name, then # this option decides whether the comment should be inserted. # Affects cmt_insert_func_header and cmt_insert_class_header. cmt_insert_before_preproc = false # false/true # # Preprocessor options # # Control indent of preprocessors inside #if blocks at brace level 0 pp_indent = ignore # ignore/add/remove/force # Whether to indent #if/#else/#endif at the brace level (true) or from column 1 (false) pp_indent_at_level = false # false/true # If pp_indent_at_level=false, specifies the number of columns to indent per level. Default=1. pp_indent_count = 1 # number # Add or remove space after # based on pp_level of #if blocks pp_space = ignore # ignore/add/remove/force # Sets the number of spaces added with pp_space pp_space_count = 0 # number # The indent for #region and #endregion in C# and '#pragma region' in C/C++ pp_indent_region = 0 # number # Whether to indent the code between #region and #endregion pp_region_indent_code = false # false/true # If pp_indent_at_level=true, sets the indent for #if, #else, and #endif when not at file-level pp_indent_if = 0 # number # Control whether to indent the code between #if, #else and #endif when not at file-level pp_if_indent_code = false # false/true # Whether to indent '#define' at the brace level (true) or from column 1 (false) pp_define_at_level = false # false/true # You can force a token to be a type with the 'type' option. # Example: # type myfoo1 myfoo2 # # You can create custom macro-based indentation using macro-open, # macro-else and macro-close. # Example: # macro-open BEGIN_TEMPLATE_MESSAGE_MAP # macro-open BEGIN_MESSAGE_MAP # macro-close END_MESSAGE_MAP # # You can assign any keyword to any type with the set option. # set func_call_user _ N_ # # The full syntax description of all custom definition config entries # is shown below: # # define custom tokens as: # - embed whitespace in token using '' escape character, or # put token in quotes # - these: ' " and ` are recognized as quote delimiters # # type token1 token2 token3 ... # ^ optionally specify multiple tokens on a single line # define def_token output_token # ^ output_token is optional, then NULL is assumed # macro-open token # macro-close token # macro-else token # set id token1 token2 ... # ^ optionally specify multiple tokens on a single line # ^ id is one of the names in token_enum.h sans the CT_ prefix, # e.g. PP_PRAGMA # # all tokens are separated by any mix of ',' commas, '=' equal signs # and whitespace (space, tab) # stxxl-1.3.1/misc/run-all-tests0000755000175000017500000002141611536141021016103 0ustar andreasandreas#!/bin/bash ############################################################################ # misc/run-all-tests # # Part of the STXXL. See http://stxxl.sourceforge.net # # Copyright (C) 2008, 2009 Andreas Beckmann # # Distributed under the Boost Software License, Version 1.0. # (See accompanying file LICENSE_1_0.txt or copy at # http://www.boost.org/LICENSE_1_0.txt) ############################################################################ # Usage: $0 [stxxl|mcstxxl|pmstxxl] [yes|no (valgrind)] [yes|no (leakreport=full)] # Environment: STXXL_TMPDIR (default: .) for location of generated input/output files ulimit -t 7200 set -o pipefail stxxl=stxxl test -n "$1" && stxxl="$1" valgrind=yes test -n "$2" && valgrind="$2" leakreport="" if [ "$3" = "yes" ]; then leakreport="--leak-check=full --show-reachable=yes" fi suppressions="" for supp in `dirname $0`/*.supp do suppressions="$suppressions --suppressions=$supp" done testresults=testresults mkdir -p $testresults AMI_SINGLE_DEVICE=/tmp/TPIE/ export AMI_SINGLE_DEVICE if ! [ -n "$STXXL_TMPDIR" -a -d "$STXXL_TMPDIR" -a -w "$STXXL_TMPDIR" ]; then STXXL_TMPDIR="." fi echo "Using STXXL_TMPDIR='$STXXL_TMPDIR'" i=0 run() { echo "==================== $stxxl valgrind=$valgrind $i: $1 ====================" cmd="$1.$stxxl.bin" bn=`basename $1` shift i=$(($i + 1)) pfx="`printf '%s/test.%s.%05d.%04d.%s' $testresults $stxxl $$ $i $bn`" rm -f stxxl.log stxxl.errlog test -x "$cmd" || return 255 echo "+ $cmd $@" | tee "$pfx.log" echo "[`date`]" | tee -a "$pfx.log" if [ "$valgrind" = "yes" ]; then valgrind --track-fds=no --log-file="$pfx.valgrind" --freelist-vol=2147483648 --max-stackframe=8388608 $suppressions $leakreport \ $cmd "$@" < /dev/null 2>&1 | tee -a "$pfx.log" result=$? else $cmd "$@" < /dev/null 2>&1 | tee -a "$pfx.log" result=$? fi echo "[`date`]" | tee -a "$pfx.log" if [ -n "$XFAIL" ]; then if [ "$result" = 0 ]; then mv "$pfx.log" "$pfx.FAIL.xfail.$result" else mv "$pfx.log" "$pfx.xfail.$result" fi else test "$result" = 0 || mv "$pfx.log" "$pfx.FAIL.$result" fi test -s stxxl.errlog && mv stxxl.errlog "$pfx.ERR" } if false; then : fi run common/stxxl_info XFAIL=1 run common/stxxl_info foo # returns -1 intentionally XFAIL=1 run common/stxxl_info foo bar # returns !0 if assertions are enabled run common/test_random run common/test_manyunits run common/test_globals run io/gen_file "$STXXL_TMPDIR/in" run utils/createdisks 1024 "$STXXL_TMPDIR/testdiskx" "$STXXL_TMPDIR/testdisky" run utils/createdisks 1000 "$STXXL_TMPDIR/testdiskx" "$STXXL_TMPDIR/testdisky" run utils/log2 run utils/malloc 1024 run utils/malloc 1024000 run utils/malloc 4000000000 run utils/pq_param #run utils/mlock 42 # does not terminate intentionally run io/benchmark_disks 0 2 256 "$STXXL_TMPDIR/testdiskx" "$STXXL_TMPDIR/testdisky" run io/flushbuffers 2 "$STXXL_TMPDIR/testdiskx" "$STXXL_TMPDIR/testdisky" run io/benchmark_disk_and_flash 0 2 "$STXXL_TMPDIR/testdiskx" "$STXXL_TMPDIR/testdisky" run io/sd_test run io/test_io "$STXXL_TMPDIR" run io/test_cancel syscall "$STXXL_TMPDIR/testdiskx" run io/test_cancel fileperblock_syscall "$STXXL_TMPDIR/testdiskx" run io/test_cancel mmap "$STXXL_TMPDIR/testdiskx" run io/test_cancel fileperblock_mmap "$STXXL_TMPDIR/testdiskx" run io/test_cancel simdisk "/tmp/testramdisk" rm -f "/tmp/testramdisk" run io/test_cancel boostfd "$STXXL_TMPDIR/testdiskx" run io/test_cancel fileperblock_boostfd "$STXXL_TMPDIR/testdiskx" run io/test_cancel memory "$STXXL_TMPDIR/testdiskx" run io/test_cancel wbtl "$STXXL_TMPDIR/testdiskx" run io/test_io_sizes syscall "$STXXL_TMPDIR/out" 5368709120 run io/test_io_sizes mmap "$STXXL_TMPDIR/out" 5368709120 run io/test_io_sizes boostfd "$STXXL_TMPDIR/out" 5368709120 #run io/benchmark_configured_disks 2 128 # our disks are usually set to RAM run io/benchmark_random_block_access 2048 1024 1000000 i run io/benchmark_random_block_access 2048 128 1000000 r run io/benchmark_random_block_access 2048 128 1000000 w run io/verify_disks 123456 0 2 w "$STXXL_TMPDIR/out" run io/verify_disks 123456 0 2 r "$STXXL_TMPDIR/out" run io/iobench_scatter_in_place 100 10 4096 "$STXXL_TMPDIR/out" # consumes out run mng/test_block_alloc_strategy run mng/test_buf_streams run mng/test_mng run mng/test_mng1 run mng/test_prefetch_pool run mng/test_write_pool run mng/test_pool_pair run mng/test_read_write_pool run mng/test_mng_recursive_alloc run mng/test_aligned run containers/bench_pqueue run containers/copy_file "$STXXL_TMPDIR/in" "$STXXL_TMPDIR/out" run containers/monotonic_pq 1000 1 run containers/pq_benchmark 1 1000000 run containers/pq_benchmark 2 1000000 run containers/stack_benchmark 1 1073741824 run containers/stack_benchmark 2 1073741824 run containers/stack_benchmark 3 1073741824 run containers/stack_benchmark 4 1073741824 run containers/test_deque 33333333 run containers/test_ext_merger run containers/test_ext_merger2 run containers/test_iterators run containers/test_many_stacks 42 run containers/test_migr_stack run containers/test_pqueue run containers/test_queue run containers/test_stack 1024 run containers/test_vector run containers/test_vector_export run containers/write_vector "$STXXL_TMPDIR/in" "$STXXL_TMPDIR/out" run containers/write_vector2 "$STXXL_TMPDIR/in" "$STXXL_TMPDIR/out" run containers/test_vector_sizes "$STXXL_TMPDIR/out" syscall run containers/test_vector_sizes "$STXXL_TMPDIR/out" mmap run containers/test_vector_sizes "$STXXL_TMPDIR/out" boostfd run containers/benchmark_naive_matrix run containers/test_map 32 run containers/test_map_random 2000 run containers/btree/test_btree 10000 run containers/btree/test_btree 100000 run containers/btree/test_btree 1000000 run containers/btree/test_const_scan 10000 run containers/btree/test_const_scan 100000 run containers/btree/test_const_scan 1000000 run containers/btree/test_corr_insert_erase 14 run containers/btree/test_corr_insert_find 14 run containers/btree/test_corr_insert_scan 14 run algo/sort_file generate "$STXXL_TMPDIR/sort_file.dat" run algo/sort_file sort "$STXXL_TMPDIR/sort_file.dat" run algo/sort_file generate "$STXXL_TMPDIR/sort_file.dat" run algo/sort_file ksort "$STXXL_TMPDIR/sort_file.dat" run algo/sort_file generate "$STXXL_TMPDIR/sort_file.dat" run algo/sort_file stable_sort "$STXXL_TMPDIR/sort_file.dat" run algo/sort_file generate "$STXXL_TMPDIR/sort_file.dat" run algo/copy_and_sort_file "$STXXL_TMPDIR/sort_file.dat" "$STXXL_TMPDIR/sorted_file.dat" test -n "$WITH_STABLE_KSORT" && run algo/sort_file generate "$STXXL_TMPDIR/sort_file.dat" test -n "$WITH_STABLE_KSORT" && run algo/sort_file stable_ksort "$STXXL_TMPDIR/sort_file.dat" run algo/test_asch 3 100 1000 42 run algo/test_ksort run algo/test_random_shuffle run algo/test_scan run algo/test_sort run algo/test_bad_cmp test -n "$WITH_STABLE_KSORT" && run algo/test_stable_ksort run stream/test_materialize run stream/test_push_sort run stream/test_sorted_runs run stream/test_stream run stream/test_stream1 run stream/test_transpose run stream/test_loop 100 -v run stream/test_loop 1000000 run io/unittest run mng/unittest rm -rf $AMI_SINGLE_DEVICE mkdir $AMI_SINGLE_DEVICE # for the tpie and bdb tests valgrind reports lots of # new/delete mismatches and off-by-one errors # due to bad partial tpie new/delete replacements run containers/tpie_stack_benchmark 1 2147483648 run containers/tpie_stack_benchmark 2 2147483648 run containers/berkeley_db_benchmark 1 100 run containers/berkeley_db_benchmark 2 10000000 run containers/berkeley_db_benchmark 3 100 run containers/berkeley_db_benchmark 4 100 run containers/berkeley_db_benchmark 5 10000000 rm -rf $AMI_SINGLE_DEVICE rm -f /var/tmp/bdb_file run containers/leda_sm_pq_benchmark 1 1000000 run containers/leda_sm_pq_benchmark 2 1000000 run containers/leda_sm_stack_benchmark 1 1073741824 run containers/leda_sm_stack_benchmark 2 1073741824 #algo/test_sort_all_parameters #algo/test_ksort_all_parameters #algo/test_stable_ksort_all_parameters for data in 1024 ; do for ram in 384 ; do for strategy in 0 1 2 3 ; do for blk_size in 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 ; do run algo/test_sort_all_parameters $data $ram $strategy $blk_size 42 run algo/test_ksort_all_parameters $data $ram $strategy $blk_size 42 test -n "$WITH_STABLE_KSORT" && \ run algo/test_stable_ksort_all_parameters $data $ram $strategy $blk_size 42 done done done done #algo/test_parallel_sort [n in MiB] [p threads] [M in MiB] [sorting algorithm: m | q | qb | s] [merging algorithm: p | s | n] for data in 768 ; do for ram in 128 ; do for threads in 1 2 3 4 ; do for sort in m q qb s ; do for merge in p s n ; do run algo/test_parallel_sort $data $threads $ram $sort $merge done done done done done exit 0 stxxl-1.3.1/misc/floating-average0000755000175000017500000000257611513611117016615 0ustar andreasandreas#!/usr/bin/perl -w ############################################################################ # misc/floating-average # # Part of the STXXL. See http://stxxl.sourceforge.net # # Copyright (C) 2007 Johannes Singler # Copyright (C) 2010 Andreas Beckmann # # Distributed under the Boost Software License, Version 1.0. # (See accompanying file LICENSE_1_0.txt or copy at # http://www.boost.org/LICENSE_1_0.txt) ############################################################################ # Calculate the floating average over $1 values in all columns # Reading from stdin, writing to stdout # Example: floating-average 3 averaged use strict; my $span = $ARGV[0]; my @sums; my @history; my $count_sum = 1; my $line_number = 0; my $line; while($line = ) { my @parts = split /\s+/, $line; my $c = 0; my $part; foreach $part(@parts) { if($part =~ /^[+-]?\d+\.?\d*([eE][+-]?\d+)?$/) { #is number if($count_sum == $span) { $sums[$c] -= $history[$line_number % $span][$c] || 0; } $history[$line_number % $span][$c] = $part; $sums[$c] += $history[$line_number % $span][$c]; printf("%14.6f ", $sums[$c] / $count_sum); ++$c; } else { print(" $part "); } } print("\n"); if($count_sum < $span) { ++$count_sum; } ++$line_number; } stxxl-1.3.1/misc/buildbot-test-autoconfig0000755000175000017500000000067411174324042020315 0ustar andreasandreas#!/bin/sh set -e rm -f make.settings make.settings.local GNUmakefile echo "########## make ##########" make echo "########## make config_gnu ##########" rm -f make.settings.local make config_gnu || true test -f make.settings.local echo "################################################################" cat make.settings.local echo "################################################################" rm -f make.settings make.settings.local stxxl-1.3.1/README0000644000175000017500000000147111504065334013376 0ustar andreasandreasDESCRIPTION STXXL is an implementation of the C++ standard template library STL for external memory (out-of-core) computations, i. e. STXXL implements containers and algorithms that can process huge volumes of data that only fit on disks. While the closeness to the STL supports ease of use and compatibility with existing applications, another design priority is high performance. DOCUMENTATION See the Doxygen documentation for installation manual and programmer documentation: http://stxxl.sourceforge.net LICENSE TERMS STXXL is distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) BUGS AND QUESTIONS If you find any bugs or have any questions, please visit the forums at http://sourceforge.net/projects/stxxl/forums stxxl-1.3.1/config_example_win0000644000175000017500000000012410622615152016267 0ustar andreasandreasdisk=c:\stxxl,70000,wincall disk=d:\stxxl,70000,wincall disk=e:\stxxl,70000,wincall stxxl-1.3.1/contrib/0000755000175000017500000000000011536252421014153 5ustar andreasandreasstxxl-1.3.1/contrib/Makefile.common0000644000175000017500000000001311535457411017101 0ustar andreasandreasTESTS = stxxl-1.3.1/contrib/GNUmakefile0000644000175000017500000000011411535457411016226 0ustar andreasandreasTOPDIR ?= .. include Makefile.common include $(TOPDIR)/Makefile.subdir.gnu stxxl-1.3.1/utils/0000755000175000017500000000000011536252421013653 5ustar andreasandreasstxxl-1.3.1/utils/pq_param.cpp0000644000175000017500000000432611032431653016161 0ustar andreasandreas/*************************************************************************** * utils/pq_param.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2003 Roman Dementiev * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #include #include #include typedef stxxl::int64 int64; int64 D(int64 m, int64 k, int64 MaxS, int64 E, int64 B) { return (m * m / 4 - (MaxS * E / (k - m)) / B); } using std::cout; using std::endl; int main() { int64 IntM = 128 * 1024 * 1024; int64 E = 4; int64 B = 8 * 1024 * 1024; //int64 Bstep = 128 * 1024; int64 MaxS = (int64(128) * int64(1024 * 1024 * 1024)) / E; for ( ; B > 4096; B = B / 2) { int64 m = 1; int64 k = IntM / B; for ( ; m < k; ++m) { int64 c = (k - m); //if( D(m,k,MaxS,E,B)>= 0 && c > 10) if ((k - m) * m * m * B / (E * 4) >= MaxS) { cout << (k - m) * (m) * (m * B / (E * 4)) << endl; cout << MaxS << endl; cout << "D: " << D(m, k, MaxS, E, B) << endl; cout << "B: " << B << endl; cout << "c: " << c << endl; cout << "k: " << k << endl; int64 Ae = m / 2; int64 Ae1 = Ae + int64(sqrt((double)D(m, k, MaxS, E, B))); int64 Ae2 = Ae - int64(sqrt((double)D(m, k, MaxS, E, B))); int64 x = c * B / E; int64 N = x / 4096; cout << "Ae : " << Ae << endl; cout << "Ae1: " << Ae1 << endl; cout << "Ae2: " << Ae2 << endl; cout << "minAe :" << (MaxS / (x * Ae)) << endl; cout << "x : " << x << endl; cout << "N : " << N << endl; int64 Cons = x * E + B * (m / 2) + MaxS * B / (x * (m / 2)); cout << "COns : " << Cons << endl; return 0; } } } cout << "No valid parameter found" << endl; } stxxl-1.3.1/utils/createdisks.cpp0000644000175000017500000001704211305236156016665 0ustar andreasandreas/*************************************************************************** * utils/createdisks.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2003 Roman Dementiev * Copyright (C) 2007 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #include #include #include #include #include #ifndef BOOST_MSVC #include #endif using stxxl::request_ptr; using stxxl::file; using stxxl::timestamp; #ifdef BLOCK_ALIGN #undef BLOCK_ALIGN #endif #define BLOCK_ALIGN 4096 #define NOREAD //#define DO_ONLY_READ #define POLL_DELAY 1000 #define RAW_ACCESS //#define WATCH_TIMES #define CHECK_AFTER_READ 0 #ifdef WATCH_TIMES void watch_times(request_ptr reqs[], unsigned n, double * out) { bool * finished = new bool[n]; unsigned count = 0; unsigned i = 0; for (i = 0; i < n; i++) finished[i] = false; while (count != n) { usleep(POLL_DELAY); i = 0; for (i = 0; i < n; i++) { if (!finished[i]) if (reqs[i]->poll()) { finished[i] = true; out[i] = timestamp(); count++; } } } delete[] finished; } void out_stat(double start, double end, double * times, unsigned n, const std::vector & names) { for (unsigned i = 0; i < n; i++) { std::cout << i << " " << names[i] << " took " << 100. * (times[i] - start) / (end - start) << " %" << std::endl; } } #endif #define MB (1024 * 1024) int main(int argc, char * argv[]) { if (argc < 3) { STXXL_MSG("Usage: " << argv[0] << " filesize_in_MiB filename1 [filename2 [filename3 ...]]"); return -1; } stxxl::int64 offset = 0; stxxl::int64 length = stxxl::int64(atoi(argv[1])) * MB; stxxl::int64 endpos = offset + length; std::vector disks_arr; for (int ii = 2; ii < argc; ++ii) { unlink(argv[ii]); std::cout << "# Add disk: " << argv[ii] << std::endl; disks_arr.push_back(argv[ii]); } const unsigned ndisks = disks_arr.size(); #ifdef BOOST_MSVC unsigned buffer_size = 64 * MB; #else unsigned buffer_size = 256 * MB; #endif const unsigned buffer_size_int = buffer_size / sizeof(int); unsigned chunks = 2; const unsigned chunk_size = buffer_size / chunks; const unsigned chunk_size_int = chunk_size / sizeof(int); unsigned i = 0, j = 0; int * buffer = (int *)stxxl::aligned_alloc(buffer_size * ndisks); file ** disks = new file *[ndisks]; request_ptr * reqs = new request_ptr[ndisks * chunks]; #ifdef WATCH_TIMES double * r_finish_times = new double[ndisks]; double * w_finish_times = new double[ndisks]; #endif for (i = 0; i < ndisks * buffer_size_int; i++) buffer[i] = i; for (i = 0; i < ndisks; i++) { #ifdef BOOST_MSVC #ifdef RAW_ACCESS disks[i] = new stxxl::wincall_file(disks_arr[i], file::CREAT | file::RDWR | file::DIRECT, i); #else disks[i] = new stxxl::wincall_file(disks_arr[i], file::CREAT | file::RDWR, i); #endif #else #ifdef RAW_ACCESS disks[i] = new stxxl::syscall_file(disks_arr[i], file::CREAT | file::RDWR | file::DIRECT, i); #else disks[i] = new stxxl::syscall_file(disks_arr[i], file::CREAT | file::RDWR, i); #endif #endif } while (offset < endpos) { const unsigned current_block_size = length ? std::min(buffer_size, endpos - offset) : buffer_size; const unsigned current_chunk_size = current_block_size / chunks; std::cout << "Disk offset " << std::setw(7) << offset / MB << " MiB: " << std::fixed; double begin = timestamp(), end; #ifndef DO_ONLY_READ for (i = 0; i < ndisks; i++) { for (j = 0; j < chunks; j++) reqs[i * chunks + j] = disks[i]->awrite(buffer + buffer_size_int * i + j * chunk_size_int, offset + j * current_chunk_size, current_chunk_size, stxxl::default_completion_handler()); } #ifdef WATCH_TIMES watch_times(reqs, ndisks, w_finish_times); #else wait_all(reqs, ndisks * chunks); #endif end = timestamp(); #if 0 std::cout << "WRITE\nDisks: " << ndisks << " \nElapsed time: " << end - begin << " \nThroughput: " << int(double(buffer_size * ndisks) / MB / (end - begin)) << " MiB/s \nPer one disk:" << int((buffer_size) / MB / (end - begin)) << " MiB/s" << std::endl; #endif #ifdef WATCH_TIMES out_stat(begin, end, w_finish_times, ndisks, disks_arr); #endif std::cout << std::setw(7) << int(double(current_block_size) / MB / (end - begin)) << " MiB/s,"; #endif #ifndef NOREAD begin = timestamp(); for (i = 0; i < ndisks; i++) { for (j = 0; j < chunks; j++) reqs[i * chunks + j] = disks[i]->aread(buffer + buffer_size_int * i + j * chunk_size_int, offset + j * current_chunk_size, current_chunk_size, stxxl::default_completion_handler()); } #ifdef WATCH_TIMES watch_times(reqs, ndisks, r_finish_times); #else wait_all(reqs, ndisks * chunks); #endif end = timestamp(); #if 0 std::cout << "READ\nDisks: " << ndisks << " \nElapsed time: " << end - begin << " \nThroughput: " << int(double(buffer_size * ndisks) / MB / (end - begin)) << " MiB/s \nPer one disk:" << int(double(buffer_size) / MB / (end - begin)) << " MiB/s" << std::endl; #endif std::cout << int(double(current_block_size) / MB / (end - begin)) << " MiB/s" << std::endl; #ifdef WATCH_TIMES out_stat(begin, end, r_finish_times, ndisks, disks_arr); #endif if (CHECK_AFTER_READ) { for (int i = 0; unsigned(i) < ndisks * buffer_size_int; i++) { if (buffer[i] != i) { int ibuf = i / buffer_size_int; int pos = i % buffer_size_int; std::cout << "Error on disk " << ibuf << " position " << std::hex << std::setw(8) << offset + pos * sizeof(int) << " got: " << std::hex << std::setw(8) << buffer[i] << " wanted: " << std::hex << std::setw(8) << i << std::dec << std::endl; i = (ibuf + 1) * buffer_size_int; // jump to next } } } #else std::cout << std::endl; #endif offset += current_block_size; } #ifdef WATCH_TIMES delete[] r_finish_times; delete[] w_finish_times; #endif delete[] reqs; for (i = 0; i < ndisks; i++) delete disks[i]; delete[] disks; stxxl::aligned_dealloc(buffer); return 0; } stxxl-1.3.1/utils/Makefile.common0000644000175000017500000000020011422247603016572 0ustar andreasandreasTESTS = pq_param log2 TESTS_NON_MSVC = malloc LIB_SRC = UTIL_BINARIES = createdisks UTIL_BINARIES_NON_MSVC = mlock stxxl-1.3.1/utils/log2.cpp0000644000175000017500000000313011025224635015216 0ustar andreasandreas/*************************************************************************** * utils/log2.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright © 2008 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #include #include using stxxl::LOG2; using stxxl::unsigned_type; template void log_i() { std::cout << i << "\t" << (i < 1000000 ? "\t" : "") << stxxl::LOG2_floor::value << "\t" << stxxl::LOG2::floor << "\t" << stxxl::LOG2::ceil << std::endl; } template void log_ipm1() { log_i(); log_i(); log_i(); std::cout << std::endl; } int main() { std::cout << "i\t\tLOG2\tLOG2\tLOG2" << std::endl; std::cout << "\t\t\tfloor\tceil" << std::endl; log_ipm1<1 << 0>(); log_ipm1<1 << 1>(); log_ipm1<1 << 2>(); log_ipm1<1 << 3>(); log_ipm1<1 << 4>(); log_ipm1<1 << 5>(); log_ipm1<1 << 6>(); log_ipm1<1 << 7>(); log_ipm1<1 << 8>(); log_ipm1<1 << 9>(); log_ipm1<1 << 10>(); log_ipm1<1 << 11>(); log_ipm1<1 << 12>(); log_ipm1<1 << 16>(); log_ipm1<1 << 24>(); log_ipm1<1 << 30>(); log_ipm1<1UL << 31>(); #if __WORDSIZE == 64 log_ipm1<1UL << 32>(); log_ipm1<1UL << 33>(); log_ipm1<1UL << 48>(); log_ipm1<1UL << 63>(); #endif } stxxl-1.3.1/utils/mlock.cpp0000644000175000017500000000253011437171771015474 0ustar andreasandreas/*************************************************************************** * utils/mlock.cpp * * Allocate some memory and mlock() it to consume physical memory. * Needs to run as root to block more than 64 KiB in default settings. * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2010 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #include #include #include #include int main(int argc, char ** argv) { if (argc == 2) { long M = atol(argv[1]); if (M > 0) { char * c = (char *)malloc(M); for (long i = 0; i < M; ++i) c[i] = 42; if (mlock(c, M) == 0) { std::cout << "mlock(, " << M << ") successful, press Ctrl-C to finish" << std::endl; while (1) sleep(86400); } else { std::cerr << "mlock(, " << M << ") failed!" << std::endl; return 1; } } } else { std::cout << "Usage: " << argv[0] << " " << std::endl; } } // vim: et:ts=4:sw=4 stxxl-1.3.1/utils/GNUmakefile0000644000175000017500000000043411401225456015725 0ustar andreasandreasTOPDIR ?= .. include Makefile.common all: tools TESTS-yes += $(TESTS_NON_MSVC) UTIL_BINARIES += $(UTIL_BINARIES_NON_MSVC) include $(TOPDIR)/Makefile.subdir.gnu tools: $(UTIL_BINARIES:=.$(bin)) #createdisks.$o: CPPFLAGS += -DNDEBUG clean:: $(RM) $(UTIL_BINARIES:=.$(bin)) stxxl-1.3.1/utils/malloc.cpp0000644000175000017500000000466611531445437015650 0ustar andreasandreas/*************************************************************************** * utils/malloc.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2003 Roman Dementiev * Copyright (C) 2009 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #include #if !defined(__APPLE__) && !defined(__FreeBSD__) #include #endif #include #include void print_malloc_stats() { #if !defined(__APPLE__) && !defined(__FreeBSD__) struct mallinfo info = mallinfo(); STXXL_MSG("MALLOC statistics BEGIN"); STXXL_MSG("==============================================================="); STXXL_MSG("non-mmapped space allocated from system (bytes): " << info.arena); STXXL_MSG("number of free chunks : " << info.ordblks); STXXL_MSG("number of fastbin blocks : " << info.smblks); STXXL_MSG("number of chunks allocated via mmap() : " << info.hblks); STXXL_MSG("total number of bytes allocated via mmap() : " << info.hblkhd); STXXL_MSG("maximum total allocated space (bytes) : " << info.usmblks); STXXL_MSG("space available in freed fastbin blocks (bytes): " << info.fsmblks); STXXL_MSG("number of bytes allocated and in use : " << info.uordblks); STXXL_MSG("number of bytes allocated but not in use : " << info.fordblks); STXXL_MSG("top-most, releasable (via malloc_trim) space : " << info.keepcost); STXXL_MSG("================================================================"); #else STXXL_MSG("MALLOC statistics are not supported on this platform"); #endif } int main(int argc, char * argv[]) { using std::cout; using std::cerr; using std::endl; if (argc < 2) { cerr << "Usage: " << argv[0] << " bytes_to_allocate" << endl; return -1; } sbrk(128 * 1024 * 1024); cout << "Nothing allocated" << endl; print_malloc_stats(); const unsigned bytes = atoi(argv[1]); char * ptr = new char[bytes]; cout << "Allocated " << bytes << " bytes" << endl; print_malloc_stats(); delete[] ptr; cout << "Deallocated " << endl; print_malloc_stats(); } stxxl-1.3.1/utils/Makefile0000644000175000017500000000217011422247603015313 0ustar andreasandreasinclude Makefile.common include ../make.settings tools: $(UTIL_BINARIES) tests: $(TESTS) #tests: $(TESTS_NON_MSVC) NDEBUG = #-DNDEBUG DEPENDENCIES = $(COMMON_FILES) $(IO_LAYER_FILES) $(MNG_LAYER_FILES) $(CONTAINER_FILES) $(ALGO_FILES) createdisks: createdisks.$(EXEEXT) createdisks.$(EXEEXT): createdisks.cpp $(DEPENDENCIES) $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c createdisks.cpp $(NDEBUG) $(LINKER) createdisks.$(OBJEXT) $(OUT)createdisks.$(EXEEXT) $(STXXL_LINKER_OPTIONS) malloc: malloc.$(EXEEXT) malloc.$(EXEEXT): malloc.cpp $(DEPENDENCIES) $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c malloc.cpp $(NDEBUG) $(LINKER) malloc.$(OBJEXT) $(OUT)malloc.$(EXEEXT) $(STXXL_LINKER_OPTIONS) pq_param: pq_param.$(EXEEXT) pq_param.$(EXEEXT): pq_param.cpp $(DEPENDENCIES) $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c pq_param.cpp $(NDEBUG) $(LINKER) pq_param.$(OBJEXT) $(OUT)pq_param.$(EXEEXT) $(STXXL_LINKER_OPTIONS) log2: log2.$(EXEEXT) log2.$(EXEEXT): log2.cpp $(DEPENDENCIES) $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c log2.cpp $(NDEBUG) $(LINKER) log2.$(OBJEXT) $(OUT)log2.$(EXEEXT) $(STXXL_LINKER_OPTIONS) clean: $(RM) $(CLEAN_TARGETS) stxxl-1.3.1/containers/0000755000175000017500000000000011536252421014660 5ustar andreasandreasstxxl-1.3.1/containers/write_vector2.cpp0000644000175000017500000000705511060745120020164 0ustar andreasandreas/*************************************************************************** * containers/write_vector2.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2006 Roman Dementiev * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #include #include #include // efficiently writes data into an stxxl::vector with overlapping of I/O and // computation template class write_vector { typedef typename ExtIterator::size_type size_type; typedef typename ExtIterator::value_type value_type; typedef typename ExtIterator::block_type block_type; typedef typename ExtIterator::const_iterator ConstExtIterator; typedef stxxl::buf_ostream buf_ostream_type; ExtIterator it; unsigned nbuffers; buf_ostream_type * outstream; public: write_vector(ExtIterator begin, unsigned nbuffers_ // buffers to use for overlapping (>=2 recommended) ) : it(begin), nbuffers(nbuffers_) { outstream = new buf_ostream_type(it.bid(), nbuffers); } value_type & operator * () { if (it.block_offset() == 0) it.block_externally_updated(); // tells the vector that the block was modified return **outstream; } write_vector & operator ++ () { ++it; ++(*outstream); return *this; } void flush() { ConstExtIterator const_out = it; while (const_out.block_offset()) { **outstream = *const_out; // might cause I/Os for loading the page that ++const_out; // contains data beyond out ++(*outstream); } it.flush(); delete outstream; outstream = NULL; } virtual ~write_vector() { if (outstream) flush(); } }; typedef unsigned char my_type; // copies a file to another file using stxxl::syscall_file; using stxxl::file; int main(int argc, char * argv[]) { if (argc < 3) { std::cout << "Usage: " << argv[0] << " input_file output_file " << std::endl; return -1; } unlink(argv[2]); // delete output file syscall_file InputFile(argv[1], file::RDONLY); // Input file object syscall_file OutputFile(argv[2], file::RDWR | file::CREAT); // Output file object typedef stxxl::vector vector_type; std::cout << "Copying file " << argv[1] << " to " << argv[2] << std::endl; vector_type InputVector(&InputFile); // InputVector is mapped to InputFile vector_type OutputVector(&OutputFile); // OutputVector is mapped to OutputFile OutputVector.resize(InputVector.size()); std::cout << "File " << argv[1] << " has size " << InputVector.size() << " bytes." << std::endl; vector_type::const_iterator it = InputVector.begin(); // creating const iterator write_vector Writer(OutputVector.begin(), 2); for ( ; it != InputVector.end(); ++it, ++Writer) // iterate through InputVector { *Writer = *it; } Writer.flush(); // flush buffers return 0; } stxxl-1.3.1/containers/tpie_stack_benchmark.cpp0000644000175000017500000001123711270157465021537 0ustar andreasandreas/*************************************************************************** * containers/tpie_stack_benchmark.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2006 Roman Dementiev * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ //! \example containers/tpie_stack_benchmark.cpp //! This is a benchmark mentioned in the paper //! R. Dementiev, L. Kettner, P. Sanders "STXXL: standard template library for XXL data sets" //! Software: Practice and Experience //! Volume 38, Issue 6, Pages 589-637, May 2008 //! DOI: 10.1002/spe.844 #include "app_config.h" #include #include // Get the AMI_stack definition. #include // Utilities for ASCII output. #include #include #include #include #define MEM_2_RESERVE (768 * 1024 * 1024) #define BLOCK_SIZE (2 * 1024 * 1024) #ifndef DISKS #define DISKS 1 #endif template struct my_record_ { char data[RECORD_SIZE]; my_record_() { } }; template void run_stack(stxxl::int64 volume) { typedef AMI_stack stack_type; MM_manager.set_memory_limit(BLOCK_SIZE * DISKS * 8); STXXL_MSG("Record size: " << sizeof(my_record) << " bytes"); stack_type Stack; stxxl::int64 ops = volume / sizeof(my_record); stxxl::int64 i; my_record cur; stxxl::timer Timer; Timer.start(); for (i = 0; i < ops; ++i) { Stack.push(cur); } Timer.stop(); STXXL_MSG("Records in Stack: " << Stack.stream_len()); if (i != Stack.stream_len()) { STXXL_MSG("Size does not match"); abort(); } STXXL_MSG("Insertions elapsed time: " << (Timer.mseconds() / 1000.) << " seconds : " << (double(volume) / (1024. * 1024. * Timer.mseconds() / 1000.)) << " MiB/s"); //////////////////////////////////////////////// Timer.reset(); Timer.start(); my_record * out; for (i = 0; i < ops; ++i) { Stack.pop(&out); } Timer.stop(); STXXL_MSG("Records in Stack: " << Stack.stream_len()); if (Stack.stream_len() != 0) { STXXL_MSG("Stack must be empty"); abort(); } STXXL_MSG("Deletions elapsed time: " << (Timer.mseconds() / 1000.) << " seconds : " << (double(volume) / (1024. * 1024. * Timer.mseconds() / 1000.)) << " MiB/s"); } int main(int argc, char * argv[]) { using std::cout; using std::endl; #ifdef BTE_COLLECTION_IMP_MMAP cout << "BTE_COLLECTION_IMP_MMAP is defined" << endl; #endif #ifdef BTE_COLLECTION_IMP_UFS cout << "BTE_COLLECTION_IMP_UFS is defined" << endl; #endif #ifdef BTE_STREAM_IMP_UFS cout << "BTE_STREAM_IMP_UFS is defined" << endl; cout << "BTE_STREAM_UFS_BLOCK_FACTOR is " << BTE_STREAM_UFS_BLOCK_FACTOR << endl; cout << "Actual block size is " << (TPIE_OS_BLOCKSIZE() * BTE_STREAM_UFS_BLOCK_FACTOR / 1024) << " KiB" << endl; #endif #ifdef BTE_STREAM_IMP_MMAP cout << "BTE_STREAM_IMP_MMAP is defined" << endl; cout << "BTE_STREAM_MMAP_BLOCK_FACTOR is " << BTE_STREAM_MMAP_BLOCK_FACTOR << endl; cout << "Actual block size is " << (TPIE_OS_BLOCKSIZE() * BTE_STREAM_MMAP_BLOCK_FACTOR / 1024) << " KiB" << endl; #endif #ifdef BTE_STREAM_IMP_STDIO cout << "BTE_STREAM_IMP_STDIO is defined" << endl; #endif cout << "TPIE_OS_BLOCKSIZE() is " << TPIE_OS_BLOCKSIZE() << endl; if (argc < 3) { STXXL_MSG("Usage: " << argv[0] << " version #volume"); STXXL_MSG("\t version = 1: TPIE stack with 4 byte records"); STXXL_MSG("\t version = 2: TPIE stack with 32 byte records"); return -1; } int version = atoi(argv[1]); stxxl::int64 volume = stxxl::atoint64(argv[2]); STXXL_MSG("Allocating array with size " << MEM_2_RESERVE << " bytes to prevent file buffering."); //int * array = new int[MEM_2_RESERVE/sizeof(int)]; int * array = (int *)malloc(MEM_2_RESERVE); std::fill(array, array + (MEM_2_RESERVE / sizeof(int)), 0); STXXL_MSG("Running version: " << version); STXXL_MSG("Data volume : " << volume << " bytes"); switch (version) { case 1: run_stack >(volume); break; case 2: run_stack >(volume); break; default: STXXL_MSG("Unsupported version " << version); } //delete [] array; free(array); } stxxl-1.3.1/containers/test_ext_merger.cpp0000644000175000017500000000521711535151017020567 0ustar andreasandreas/*************************************************************************** * containers/test_ext_merger.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2003 Roman Dementiev * Copyright (C) 2009 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #include #include #include using stxxl::priority_queue_local::ext_merger; using stxxl::priority_queue_local::loser_tree; typedef int my_type; typedef stxxl::typed_block<4096, my_type> block_type; struct dummy_merger { int & cnt; dummy_merger(int & c) : cnt(c) { } template void multi_merge(OutputIterator b, OutputIterator e) { while (b != e) { *b = cnt; ++b; ++cnt; } } }; struct my_cmp : public std::greater { my_type min_value() const { return (std::numeric_limits::max)(); } my_type max_value() const { return (std::numeric_limits::min)(); } }; my_type * make_sequence(dummy_merger & dummy, int l) { my_type * seq = new my_type[l + 1]; // + sentinel dummy.multi_merge(seq, seq + l); seq[l] = my_cmp().min_value(); // sentinel return seq; } int main() { stxxl::read_write_pool pool(1, 2); int cnt = 0; dummy_merger dummy(cnt); std::vector output(1024 * 3); ext_merger merger(&pool); merger.insert_segment(dummy, 1024 * 3); cnt = 20; merger.insert_segment(dummy, 1024 * 4); cnt = 10; merger.insert_segment(dummy, 1024 * 4); cnt = -100; merger.insert_segment(dummy, 1024 * 4); merger.insert_segment(dummy, 1024 * 4); merger.multi_merge(output.begin(), output.end()); loser_tree loser; my_type * seq1 = make_sequence(dummy, 1024); cnt = 20; my_type * seq2 = make_sequence(dummy, 1024); cnt = 10; my_type * seq3 = make_sequence(dummy, 1024); cnt = -100; my_type * seq4 = make_sequence(dummy, 1024); my_type * out = new my_type[4 * 1024]; loser.init(); loser.insert_segment(seq1, 1024); loser.insert_segment(seq2, 1024); loser.insert_segment(seq3, 1024); loser.insert_segment(seq4, 1024); loser.multi_merge(out, out + 1024); std::copy(out, out + 1024, std::ostream_iterator(std::cout, "\n")); delete[] out; } stxxl-1.3.1/containers/benchmark_naive_matrix.cpp0000644000175000017500000000542211500030337022056 0ustar andreasandreas/*************************************************************************** * containers/benchmark_naive_matrix.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2010 Johannes Singler * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ //! \example containers/benchmark_naive_matrix.cpp //! This is an example of how to represent a 2D matrix by using an \c stxxl::vector. //! DISCLAIMER: The approach is very basic and the matrix multiplication is NOT I/O-EFFICIENT. #include #include template class matrix2d { stxxl::vector v; stxxl::unsigned_type width, height; public: matrix2d(stxxl::unsigned_type width, stxxl::unsigned_type height) : width(width), height(height) { v.resize(width * height); } stxxl::unsigned_type get_width() const { return width; } stxxl::unsigned_type get_height() const { return height; } T & element(stxxl::unsigned_type x, stxxl::unsigned_type y) { //row-major return v[y * width + x]; } const T & const_element(stxxl::unsigned_type x, stxxl::unsigned_type y) const { //row-major return v[y * width + x]; } }; template void matrix_multiply(const matrix2d & a, const matrix2d & b, matrix2d & c) { assert(a.get_width() == b.get_height()); assert(b.get_height() == c.get_height()); assert(b.get_width() == c.get_width()); for (stxxl::unsigned_type y = 0; y < c.get_height(); ++y) for (stxxl::unsigned_type x = 0; x < c.get_width(); ++x) { c.element(x, y) = 0; for (stxxl::unsigned_type t = 0; t < a.get_width(); ++t) c.element(x, y) += a.const_element(t, y) * b.const_element(x, t); } } int main() { const stxxl::unsigned_type width = 416, height = 416; try { matrix2d a(width, height), b(width, height), c(width, height); for (stxxl::unsigned_type y = 0; y < height; ++y) for (stxxl::unsigned_type x = 0; x < width; ++x) { a.element(x, y) = 1.0; b.element(x, y) = 1.0; c.element(x, y) = 1.0; } matrix_multiply(a, b, c); std::cout << c.const_element(0, 0) << std::endl; std::cout << c.const_element(width - 1, height - 1) << std::endl; } catch (const std::exception & ex) { STXXL_MSG("Caught exception: " << ex.what()); } catch (...) { STXXL_MSG("Caught unknown exception."); } return 0; } stxxl-1.3.1/containers/test_vector.cpp0000644000175000017500000001000311535151017017715 0ustar andreasandreas/*************************************************************************** * containers/test_vector.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2002, 2003, 2006 Roman Dementiev * Copyright (C) 2010 Johannes Singler * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ //! \example containers/test_vector.cpp //! This is an example of use of \c stxxl::vector and //! \c stxxl::VECTOR_GENERATOR. Vector type is configured //! to store 64-bit integers and have 2 pages each of 1 block #include #include #include #include struct element // 24 bytes, not a power of 2 intentionally { stxxl::int64 key; stxxl::int64 load0; stxxl::int64 load1; element & operator = (stxxl::int64 i) { key = i; load0 = i + 42; load1 = i ^ 42; return *this; } bool operator == (const element & e2) const { return key == e2.key && load0 == e2.load0 && load1 == e2.load1; } }; struct counter { int value; counter(int v) : value(v) { } int operator () () { int old_val = value; value++; return old_val; } }; template void test_const_iterator(const my_vec_type & x) { typename my_vec_type::const_iterator i = x.begin(); i = x.end() - 1; i.block_externally_updated(); i.flush(); i++; ++i; --i; i--; *i; } int main() { try { // use non-randomized striping to avoid side effects on random generator typedef stxxl::VECTOR_GENERATOR::result vector_type; vector_type v(64 * 1024 * 1024 / sizeof(element)); // test assignment const_iterator = iterator vector_type::const_iterator c_it = v.begin(); STXXL_UNUSED(c_it); unsigned int big_size = 1024 * 1024 * 2 * 16 * 16; typedef stxxl::vector vec_big; vec_big my_vec(big_size); vec_big::iterator big_it = my_vec.begin(); big_it += 6; test_const_iterator(v); stxxl::random_number32 rnd; int offset = rnd(); STXXL_MSG("write " << v.size() << " elements"); stxxl::ran32State = 0xdeadbeef; vector_type::size_type i; // fill the vector with increasing sequence of integer numbers for (i = 0; i < v.size(); ++i) { v[i].key = i + offset; assert(v[i].key == stxxl::int64(i + offset)); } // fill the vector with random numbers stxxl::generate(v.begin(), v.end(), stxxl::random_number32(), 4); v.flush(); STXXL_MSG("seq read of " << v.size() << " elements"); stxxl::ran32State = 0xdeadbeef; // testing swap vector_type a; std::swap(v, a); std::swap(v, a); for (i = 0; i < v.size(); i++) assert(v[i].key == rnd()); // check again STXXL_MSG("clear"); v.clear(); stxxl::ran32State = 0xdeadbeef + 10; v.resize(64 * 1024 * 1024 / sizeof(element)); STXXL_MSG("write " << v.size() << " elements"); stxxl::generate(v.begin(), v.end(), stxxl::random_number32(), 4); stxxl::ran32State = 0xdeadbeef + 10; STXXL_MSG("seq read of " << v.size() << " elements"); for (i = 0; i < v.size(); i++) assert(v[i].key == rnd()); STXXL_MSG("copy vector of " << v.size() << " elements"); vector_type v_copy0(v); assert(v == v_copy0); vector_type v_copy1; v_copy1 = v; assert(v == v_copy1); } catch (const std::exception & ex) { STXXL_MSG("Caught exception: " << ex.what()); } catch (...) { STXXL_MSG("Caught unknown exception."); } return 0; } stxxl-1.3.1/containers/map_test_handlers.h0000644000175000017500000000633611513611117020531 0ustar andreasandreas/*************************************************************************** * containers/map_test_handlers.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2004, 2005 Thomas Nowak * Copyright (C) 2006 Roman Dementiev * Copyright (C) 2010 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ //! \file map_test_handlers.h //! \brief This file contains help functions for testing of stxxl::map. #ifndef STXXL_TEST_HEADER__MAP_TEST_HANDLERS_H_ #define STXXL_TEST_HEADER__MAP_TEST_HANDLERS_H_ #include __STXXL_BEGIN_NAMESPACE // *********************************************** // THERE // *********************************************** template bool there(const MAPTYPE & map_, const typename MAPTYPE::key_type & key, const typename MAPTYPE::mapped_type & data) { typename MAPTYPE::const_iterator iter = map_.find(key); if (!(iter->second == data)) { STXXL_VERBOSE2("iter=(" << (*iter).first << ":" << (*iter).second << ")"); STXXL_VERBOSE2("key=" << key); STXXL_VERBOSE2("data=" << data); return false; } return true; } // *********************************************** // IS EQUAL END // *********************************************** template bool is_equal_end(const MAPTYPE & map_, typename MAPTYPE::const_iterator & iter) { return iter == map_.end(); } // *********************************************** // IS SAME // *********************************************** template bool is_same(value_type & v1, value_type & v2) { return v1.first == v2.first && v1.second == v2.second; } template bool is_same(const value_type & v1, const value_type & v2) { return v1.first == v2.first && v1.second == v2.second; } // *********************************************** // NOT THERE // *********************************************** template bool not_there(const MAPTYPE & map_, const typename MAPTYPE::key_type & key) { return map_.find(key) == map_.end(); } // *********************************************** // IS EMPTY // *********************************************** template bool is_empty(const MAPTYPE & map_) { return map_.empty(); } // *********************************************** // IS END // *********************************************** template bool is_end(MAPTYPE & map_, typename MAPTYPE::iterator & iter) { return iter == map_.end(); } template bool is_end(const MAPTYPE & map_, typename MAPTYPE::const_iterator & iter) { return iter == map_.end(); } // *********************************************** // IS SIZE // *********************************************** template bool is_size(const MAPTYPE & map_, const typename MAPTYPE::size_type size) { return map_.size() == size; } __STXXL_END_NAMESPACE #endif // !STXXL_TEST_HEADER__MAP_TEST_HANDLERS_H_ stxxl-1.3.1/containers/test_pqueue.cpp0000644000175000017500000000737211535151017017736 0ustar andreasandreas/*************************************************************************** * containers/test_pqueue.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2003 Roman Dementiev * Copyright (C) 2009 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ //! \example containers/test_pqueue.cpp //! This is an example of how to use \c stxxl::PRIORITY_QUEUE_GENERATOR //! and \c stxxl::priority_queue #include #include #include #define RECORD_SIZE 128 struct my_type { typedef int key_type; key_type key; char data[RECORD_SIZE - sizeof(key_type)]; my_type() { } explicit my_type(key_type k) : key(k) { #ifdef STXXL_VALGRIND_AVOID_UNINITIALIZED_WRITE_ERRORS memset(data, 0, sizeof(data)); #endif } }; std::ostream & operator << (std::ostream & o, const my_type & obj) { o << obj.key; return o; } struct my_cmp : std::binary_function // greater { bool operator () (const my_type & a, const my_type & b) const { return a.key > b.key; } my_type min_value() const { return my_type((std::numeric_limits::max)()); } }; int main() { /* unsigned BufferSize1_ = 32, // equalize procedure call overheads etc. unsigned N_ = 512, // bandwidth unsigned IntKMAX_ = 64, // maximal arity for internal mergers unsigned IntLevels_ = 4, unsigned BlockSize_ = (2*1024*1024), unsigned ExtKMAX_ = 64, // maximal arity for external mergers unsigned ExtLevels_ = 2, */ //typedef priority_queue > pq_type; const unsigned volume = 1024 * 1024; // in KiB typedef stxxl::PRIORITY_QUEUE_GENERATOR gen; typedef gen::result pq_type; typedef pq_type::block_type block_type; STXXL_MSG("Block size: " << block_type::raw_size); STXXL_MSG("AI: " << gen::AI); STXXL_MSG("X : " << gen::X); STXXL_MSG("N : " << gen::N); STXXL_MSG("AE: " << gen::AE); stxxl::timer Timer; Timer.start(); const unsigned mem_for_pools = 128 * 1024 * 1024; stxxl::read_write_pool pool((mem_for_pools / 2) / block_type::raw_size, (mem_for_pools / 2) / block_type::raw_size); pq_type p(pool); stxxl::int64 nelements = stxxl::int64(volume * 1024 / sizeof(my_type)), i; STXXL_MSG("Internal memory consumption of the priority queue: " << p.mem_cons() << " B"); STXXL_MSG("Max elements: " << nelements); for (i = 0; i < nelements; i++) { if ((i % (1024 * 1024)) == 0) STXXL_MSG("Inserting element " << i); p.push(my_type(nelements - i)); } Timer.stop(); STXXL_MSG("Time spent for filling: " << Timer.seconds() << " s"); // test swap pq_type p1(pool); std::swap(p, p1); std::swap(p, p1); STXXL_MSG("Internal memory consumption of the priority queue: " << p.mem_cons() << " B"); Timer.reset(); Timer.start(); for (i = 0; i < (nelements); ++i) { assert(!p.empty()); //STXXL_MSG( p.top() ); assert(p.top().key == i + 1); p.pop(); if ((i % (1024 * 1024)) == 0) STXXL_MSG("Element " << i << " popped"); } Timer.stop(); STXXL_MSG("Time spent for removing elements: " << Timer.seconds() << " s"); STXXL_MSG("Internal memory consumption of the priority queue: " << p.mem_cons() << " B"); } stxxl-1.3.1/containers/test_stack.cpp0000644000175000017500000001214711513611117017531 0ustar andreasandreas/*************************************************************************** * containers/test_stack.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2003 Roman Dementiev * Copyright (C) 2010 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ //! \example containers/test_stack.cpp //! This is an example of how to use \c stxxl::STACK_GENERATOR class //! to generate an \b external stack type //! with \c stxxl::grow_shrink_stack implementation, \b four blocks per page, //! block size \b 4096 bytes #include template void test_lvalue_correctness(stack_type & stack, int a, int b) { int i; assert(stack.empty()); for (i = 0; i < a; ++i) stack.push(i); for (i = 0; i < b; ++i) stack.push(i); for (i = 0; i < b; ++i) stack.pop(); stack.top() = 0xbeeff00d; for (i = 0; i < b; ++i) stack.push(i); for (i = 0; i < b; ++i) stack.pop(); if ((stack.top() != int(0xbeeff00d))) { STXXL_ERRMSG("STACK MISMATCH AFTER top() LVALUE MODIFICATION (0x" << std::hex << stack.top() << " != 0xbeeff00d)"); assert(stack.top() == int(0xbeeff00d)); } for (i = 0; i < a; ++i) stack.pop(); } template void simple_test(stack_type & my_stack, int test_size) { int i; for (i = 0; i < test_size; i++) { my_stack.push(i); assert(my_stack.top() == i); assert(my_stack.size() == i + 1); } for (i = test_size - 1; i >= 0; i--) { assert(my_stack.top() == i); my_stack.pop(); assert(my_stack.size() == i); } for (i = 0; i < test_size; i++) { my_stack.push(i); assert(my_stack.top() == i); assert(my_stack.size() == i + 1); } // test swap stack_type s2; std::swap(s2, my_stack); std::swap(s2, my_stack); for (i = test_size - 1; i >= 0; i--) { assert(my_stack.top() == i); my_stack.pop(); assert(my_stack.size() == i); } std::stack int_stack; for (i = 0; i < test_size; i++) { int_stack.push(i); assert(int_stack.top() == i); assert(int(int_stack.size()) == i + 1); } stack_type my_stack1(int_stack); for (i = test_size - 1; i >= 0; i--) { assert(my_stack1.top() == i); my_stack1.pop(); assert(my_stack1.size() == i); } STXXL_MSG("Test 1 passed."); test_lvalue_correctness(my_stack, 4 * 4096 / 4 * 2, 4 * 4096 / 4 * 2 * 20); } int main(int argc, char * argv[]) { typedef stxxl::STACK_GENERATOR::result ext_normal_stack_type; typedef stxxl::STACK_GENERATOR::result ext_migrating_stack_type; typedef stxxl::STACK_GENERATOR::result ext_stack_type; typedef stxxl::STACK_GENERATOR::result ext_stack_type2; if (argc < 2) { STXXL_MSG("Usage: " << argv[0] << " test_size_in_pages"); return -1; } { ext_normal_stack_type my_stack; simple_test(my_stack, atoi(argv[1]) * 4 * 4096 / sizeof(int)); } { ext_migrating_stack_type my_stack; //simple_test(my_stack, atoi(argv[1]) * 4 * 4096 / sizeof(int)); } { ext_stack_type my_stack; simple_test(my_stack, atoi(argv[1]) * 4 * 4096 / sizeof(int)); } { // prefetch/write pool with 10 blocks prefetching and 10 block write cache (> D is recommended) stxxl::read_write_pool pool(10, 10); // create a stack that does not prefetch (level of prefetch aggressiveness 0) ext_stack_type2 my_stack(pool, 0); int test_size = atoi(argv[1]) * 4 * 4096 / sizeof(int), i; for (i = 0; i < test_size; i++) { my_stack.push(i); assert(my_stack.top() == i); assert(my_stack.size() == i + 1); } my_stack.set_prefetch_aggr(10); for (i = test_size - 1; i >= 0; i--) { assert(my_stack.top() == i); my_stack.pop(); assert(my_stack.size() == i); } for (i = 0; i < test_size; i++) { my_stack.push(i); assert(my_stack.top() == i); assert(my_stack.size() == i + 1); } // test swap ext_stack_type2 s2(pool, 0); std::swap(s2, my_stack); std::swap(s2, my_stack); for (i = test_size - 1; i >= 0; i--) { assert(my_stack.top() == i); my_stack.pop(); assert(my_stack.size() == i); } STXXL_MSG("Test 2 passed."); test_lvalue_correctness(my_stack, 4 * 4096 / 4 * 2, 4 * 4096 / 4 * 2 * 20); } return 0; } // vim: et:ts=4:sw=4 stxxl-1.3.1/containers/monotonic_pq.cpp0000644000175000017500000003411711535151017020075 0ustar andreasandreas/*************************************************************************** * containers/monotonic_pq.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2003 Roman Dementiev * Copyright (C) 2007, 2009 Johannes Singler * Copyright (C) 2008, 2009 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #include #include #define STXXL_PARALLEL_PQ_MULTIWAY_MERGE_EXTERNAL 1 #define STXXL_PARALLEL_PQ_MULTIWAY_MERGE_INTERNAL 1 #define STXXL_PARALLEL_PQ_MULTIWAY_MERGE_DELETE_BUFFER 1 #define TINY_PQ 0 #define MANUAL_PQ 0 #define SIDE_PQ 1 // compare with second, in-memory PQ (needs a lot of memory) #include #include #include const stxxl::unsigned_type mega = 1024 * 1024; //1 * 1024 does not work here //const int block_size = STXXL_DEFAULT_BLOCK_SIZE(my_type); const stxxl::unsigned_type block_size = 4 * mega; #define RECORD_SIZE 16 #define LOAD 0 typedef stxxl::uint64 my_key_type; #define MAGIC 123 struct my_type { typedef my_key_type key_type; key_type key; #if LOAD key_type load; char data[RECORD_SIZE - 2 * sizeof(key_type)]; #else char data[RECORD_SIZE - sizeof(key_type)]; #endif my_type() { } my_type(key_type __key) : key(__key) { } #if LOAD my_type(key_type __key, key_type __load) : key(__key), load(__load) { } #endif void operator = (const key_type & __key) { key = __key; } #if LOAD void operator = (const my_type & mt) { key = mt.key; load = mt.load; } bool operator == (const my_type & mt) { return (key == mt.key) && (load = mt.load); } #else void operator = (const my_type & mt) { key = mt.key; } bool operator == (const my_type & mt) { return key == mt.key; } #endif }; std::ostream & operator << (std::ostream & o, const my_type & obj) { o << obj.key; #if LOAD o << "/" << obj.load; #endif return o; } //STXXL priority queue is a _maximum_ PQ. "Greater" comparator makes this a "minimum" PQ again. struct my_cmp /*: public std::binary_function*/ // greater { typedef my_type first_argument_type; typedef my_type second_argument_type; typedef bool result_type; bool operator () (const my_type & a, const my_type & b) const { return a.key > b.key; } my_type min_value() const { #if LOAD return my_type((std::numeric_limits::max)(), MAGIC); #else return my_type((std::numeric_limits::max)()); #endif } my_type max_value() const { #if LOAD return my_type((std::numeric_limits::min)(), MAGIC); #else return my_type((std::numeric_limits::min)()); #endif } }; int main(int argc, char * argv[]) { if (argc < 3) { std::cout << "Usage: " << argv[0] << " [n in MiB]" #if defined(__MCSTL__) || defined(STXXL_PARALLEL_MODE) << " [p threads]" #endif << std::endl; return -1; } STXXL_MSG("----------------------------------------"); stxxl::config::get_instance(); std::string Flags = std::string("") #if STXXL_CHECK_ORDER_IN_SORTS + " STXXL_CHECK_ORDER_IN_SORTS" #endif #ifdef NDEBUG + " NDEBUG" #endif #if TINY_PQ + " TINY_PQ" #endif #if MANUAL_PQ + " MANUAL_PQ" #endif #if SIDE_PQ + " SIDE_PQ" #endif #if STXXL_PARALLEL_PQ_MULTIWAY_MERGE_INTERNAL + " STXXL_PARALLEL_PQ_MULTIWAY_MERGE_INTERNAL" #endif #if STXXL_PARALLEL_PQ_MULTIWAY_MERGE_EXTERNAL + " STXXL_PARALLEL_PQ_MULTIWAY_MERGE_EXTERNAL" #endif #if STXXL_PARALLEL_PQ_MULTIWAY_MERGE_DELETE_BUFFER + " STXXL_PARALLEL_PQ_MULTIWAY_MERGE_DELETE_BUFFER" #endif ; STXXL_MSG("Flags:" << Flags); unsigned long megabytes = atoi(argv[1]); #ifdef __MCSTL__ int num_threads = atoi(argv[2]); STXXL_MSG("Threads: " << num_threads); mcstl::SETTINGS::num_threads = num_threads; mcstl::SETTINGS::force_sequential = false; mcstl::SETTINGS::sort_algorithm = mcstl::SETTINGS::QS_BALANCED; mcstl::SETTINGS::sort_splitting = mcstl::SETTINGS::SAMPLING; mcstl::SETTINGS::sort_minimal_n = 1000; mcstl::SETTINGS::sort_mwms_oversampling = 10; mcstl::SETTINGS::merge_splitting = mcstl::SETTINGS::SAMPLING; mcstl::SETTINGS::merge_minimal_n = 1000; mcstl::SETTINGS::merge_oversampling = 10; mcstl::SETTINGS::multiway_merge_algorithm = mcstl::SETTINGS::LOSER_TREE; mcstl::SETTINGS::multiway_merge_splitting = mcstl::SETTINGS::EXACT; mcstl::SETTINGS::multiway_merge_oversampling = 10; mcstl::SETTINGS::multiway_merge_minimal_n = 1000; mcstl::SETTINGS::multiway_merge_minimal_k = 2; #elif defined(STXXL_PARALLEL_MODE) int num_threads = atoi(argv[2]); STXXL_MSG("Threads: " << num_threads); omp_set_num_threads(num_threads); __gnu_parallel::_Settings parallel_settings(__gnu_parallel::_Settings::get()); parallel_settings.sort_algorithm = __gnu_parallel::QS_BALANCED; parallel_settings.sort_splitting = __gnu_parallel::SAMPLING; parallel_settings.sort_minimal_n = 1000; parallel_settings.sort_mwms_oversampling = 10; parallel_settings.merge_splitting = __gnu_parallel::SAMPLING; parallel_settings.merge_minimal_n = 1000; parallel_settings.merge_oversampling = 10; parallel_settings.multiway_merge_algorithm = __gnu_parallel::LOSER_TREE; parallel_settings.multiway_merge_splitting = __gnu_parallel::EXACT; parallel_settings.multiway_merge_oversampling = 10; parallel_settings.multiway_merge_minimal_n = 1000; parallel_settings.multiway_merge_minimal_k = 2; __gnu_parallel::_Settings::set(parallel_settings); #endif const stxxl::unsigned_type mem_for_queue = 512 * mega; const stxxl::unsigned_type mem_for_pools = 512 * mega; #if TINY_PQ stxxl::STXXL_UNUSED(mem_for_queue); const unsigned BufferSize1 = 32; // equalize procedure call overheads etc. const unsigned N = (1 << 9) / sizeof(my_type); // minimal sequence length const unsigned IntKMAX = 8; // maximal arity for internal mergersq const unsigned IntLevels = 2; // number of internal levels const unsigned BlockSize = (4 * mega); const unsigned ExtKMAX = 8; // maximal arity for external mergers const unsigned ExtLevels = 2; // number of external levels typedef stxxl::priority_queue< stxxl::priority_queue_config< my_type, my_cmp, BufferSize1, N, IntKMAX, IntLevels, BlockSize, ExtKMAX, ExtLevels > > pq_type; #elif MANUAL_PQ stxxl::STXXL_UNUSED(mem_for_queue); const unsigned BufferSize1 = 32; // equalize procedure call overheads etc. const unsigned N = (1 << 20) / sizeof(my_type); // minimal sequence length const unsigned IntKMAX = 16; // maximal arity for internal mergersq const unsigned IntLevels = 2; // number of internal levels const unsigned BlockSize = (4 * mega); const unsigned ExtKMAX = 32; // maximal arity for external mergers const unsigned ExtLevels = 2; // number of external levels typedef stxxl::priority_queue< stxxl::priority_queue_config< my_type, my_cmp, BufferSize1, N, IntKMAX, IntLevels, BlockSize, ExtKMAX, ExtLevels > > pq_type; #else const stxxl::uint64 volume = stxxl::uint64(200000) * mega; // in bytes typedef stxxl::PRIORITY_QUEUE_GENERATOR gen; typedef gen::result pq_type; // BufferSize1 = Config::BufferSize1, // N = Config::N, // IntKMAX = Config::IntKMAX, // IntLevels = Config::IntLevels, // ExtLevels = Config::ExtLevels, // Levels = Config::IntLevels + Config::ExtLevels, // BlockSize = Config::BlockSize, // ExtKMAX = Config::ExtKMAX /* STXXL_MSG ( "Blocks fitting into internal memory m: "<, my_cmp> side_pq; #endif my_type side_pq_least; STXXL_MSG("op-sequence(monotonic pq): ( push, pop, push ) * n"); for (i = 0; i < nelements; ++i) { if ((i % mega) == 0) STXXL_MSG( std::fixed << std::setprecision(2) << std::setw(5) << (100.0 * i / nelements) << "% " << "Inserting element " << i << " top() == " << least.key << " @ " << std::setprecision(3) << Timer.seconds() << " s" << std::setprecision(6) << std::resetiosflags(std::ios_base::floatfield)); //monotone priority queue r = least.key + rand() % modulo; sum_input += r; p.push(my_type(r)); #if SIDE_PQ side_pq.push(my_type(r)); #endif least = p.top(); sum_output += least.key; p.pop(); #if SIDE_PQ side_pq_least = side_pq.top(); side_pq.pop(); if (!(side_pq_least == least)) STXXL_MSG("Wrong result at " << i << " " << side_pq_least.key << " != " << least.key); #endif if (cmp(last_least, least)) { STXXL_MSG("Wrong order at " << i << " " << last_least.key << " > " << least.key); } else last_least = least; r = least.key + rand() % modulo; sum_input += r; p.push(my_type(r)); #if SIDE_PQ side_pq.push(my_type(r)); #endif } Timer.stop(); STXXL_MSG("Time spent for filling: " << Timer.seconds() << " s"); STXXL_MSG("Internal memory consumption of the priority queue: " << p.mem_cons() << " B"); stxxl::stats_data sd_middle(*stxxl::stats::get_instance()); std::cout << sd_middle - sd_start; Timer.reset(); Timer.start(); STXXL_MSG("op-sequence(monotonic pq): ( pop, push, pop ) * n"); for (i = 0; i < (nelements); ++i) { assert(!p.empty()); least = p.top(); sum_output += least.key; p.pop(); #if SIDE_PQ side_pq_least = side_pq.top(); side_pq.pop(); if (!(side_pq_least == least)) { STXXL_VERBOSE1("" << side_pq_least << " != " << least); } #endif if (cmp(last_least, least)) { STXXL_MSG("Wrong result at " << i << " " << last_least.key << " > " << least.key); } else last_least = least; r = least.key + rand() % modulo; sum_input += r; p.push(my_type(r)); #if SIDE_PQ side_pq.push(my_type(r)); #endif least = p.top(); sum_output += least.key; p.pop(); #if SIDE_PQ side_pq_least = side_pq.top(); side_pq.pop(); if (!(side_pq_least == least)) { STXXL_VERBOSE1("" << side_pq_least << " != " << least); } #endif if (cmp(last_least, least)) { STXXL_MSG("Wrong result at " << i << " " << last_least.key << " > " << least.key); } else last_least = least; if ((i % mega) == 0) STXXL_MSG( std::fixed << std::setprecision(2) << std::setw(5) << (100.0 * i / nelements) << "% " << "Popped element " << i << " == " << least.key << " @ " << std::setprecision(3) << Timer.seconds() << " s" << std::setprecision(6) << std::resetiosflags(std::ios_base::floatfield)); } STXXL_MSG("Last element " << i << " popped"); Timer.stop(); if (sum_input != sum_output) STXXL_MSG("WRONG sum! " << sum_input << " - " << sum_output << " = " << (sum_output - sum_input) << " / " << (sum_input - sum_output)); STXXL_MSG("Time spent for removing elements: " << Timer.seconds() << " s"); STXXL_MSG("Internal memory consumption of the priority queue: " << p.mem_cons() << " B"); std::cout << stxxl::stats_data(*stxxl::stats::get_instance()) - sd_middle; std::cout << *stxxl::stats::get_instance(); assert(sum_input == sum_output); } stxxl-1.3.1/containers/app_config.h0000644000175000017500000001052411254152470017140 0ustar andreasandreas// // File: app_config.h // Authors: Darren Erik Vengroff // Octavian Procopiuc // // Created: 10/6/94 // // $Id: app_config.h,v 1.36 2004/08/17 16:49:16 jan Exp $ // #ifndef _APP_CONFIG_H #define _APP_CONFIG_H // Get the configuration as set up by the TPIE configure script. #include // <><><><><><><><><><><><><><><><><><><><><><> // // <><><><><><><> Developer use <><><><><><><> // // <><><><><><><><><><><><><><><><><><><><><><> // #define USE_LIBAIO 0 // Set up some defaults for the test applications #include #include // for size_t #include // for random() #define DEFAULT_TEST_SIZE (20000000) #define DEFAULT_RANDOM_SEED 17 #define DEFAULT_TEST_MM_SIZE (1024 * 1024 * 32) extern bool verbose; extern TPIE_OS_SIZE_T test_mm_size; extern TPIE_OS_OFFSET test_size; extern int random_seed; // <><><><><><><><><><><><><><><><><><><><><><> // // <><><> Choose default BTE COLLECTION <><><> // // <><><><><><><><><><><><><><><><><><><><><><> // #if (!defined (BTE_COLLECTION_IMP_MMAP) && !defined (BTE_COLLECTION_IMP_UFS) && !defined (BTE_COLLECTION_IMP_USER_DEFINED)) // Define only one (default is BTE_COLLECTION_IMP_MMAP) #define BTE_COLLECTION_IMP_MMAP //#define BTE_COLLECTION_IMP_UFS //#define BTE_COLLECTION_IMP_USER_DEFINED #endif // <><><><><><><><><><><><><><><><><><><><><><> // // <><><><><><> Choose BTE STREAM <><><><><><> // // <><><><><><><><><><><><><><><><><><><><><><> // // Define only one (default is BTE_STREAM_IMP_UFS) #define BTE_STREAM_IMP_UFS //#define BTE_STREAM_IMP_MMAP //#define BTE_STREAM_IMP_STDIO //#define BTE_STREAM_IMP_USER_DEFINED // <><><><><><><><><><><><><><><><><><><><><><><><> // // <> BTE_COLLECTION_MMAP configuration options <> // // <><><><><><><><><><><><><><><><><><><><><><><><> // // Define write behavior. // Allowed values: // 0 (synchronous writes) // 1 (asynchronous writes using MS_ASYNC - see msync(2)) // 2 (asynchronous bulk writes) [default] #ifndef BTE_COLLECTION_MMAP_LAZY_WRITE #define BTE_COLLECTION_MMAP_LAZY_WRITE 2 #endif // <><><><><><><><><><><><><><><><><><><><><><><><> // // <> BTE_COLLECTION_UFS configuration options <> // // <><><><><><><><><><><><><><><><><><><><><><><><> // // <><><><><><><><><><><><><><><><><><><><><><><><> // // <><> BTE_STREAM_MMAP configuration options <><> // // <><><><><><><><><><><><><><><><><><><><><><><><> // #ifdef BTE_STREAM_IMP_MMAP // Define logical blocksize factor (default is 32) #ifndef BTE_STREAM_MMAP_BLOCK_FACTOR #ifdef _WIN32 #define BTE_STREAM_MMAP_BLOCK_FACTOR 4 #else #define BTE_STREAM_MMAP_BLOCK_FACTOR 512 #endif #endif // Enable/disable TPIE read ahead; default is enabled (set to 1) //#define BTE_STREAM_MMAP_READ_AHEAD 1 // read ahead method, ignored unless BTE_STREAM_MMAP_READ_AHEAD is set // to 1; if USE_LIBAIO is enabled, use asynchronous IO read ahead; // otherwise use use mmap-based read ahead; default is mmap-based read // ahead (USE_LIBAIO not defined) //#define USE_LIBAIO #endif // <><><><><><><><><><><><><><><><><><><><><><><><> // // <><> BTE_STREAM_UFS configuration options <><><> // // <><><><><><><><><><><><><><><><><><><><><><><><> // #ifdef BTE_STREAM_IMP_UFS // Define logical blocksize factor (default is 32) #ifndef BTE_STREAM_UFS_BLOCK_FACTOR #ifdef _WIN32 #define BTE_STREAM_UFS_BLOCK_FACTOR 4 #else #define BTE_STREAM_UFS_BLOCK_FACTOR 512 #endif #endif // Enable/disable TPIE read ahead; default is disabled (set to 0) #define BTE_STREAM_UFS_READ_AHEAD 0 // read ahead method, ignored unless BTE_STREAM_UFS_READ_AHEAD is set // to 1; if USE_LIBAIO is set to 1, use asynchronous IO read ahead; // otherwise no TPIE read ahead is done; default is disabled (set to 0) #define USE_LIBAIO 0 #endif // <><><><><><><><><><><><><><><><><><><><><><><><><><><><><><> // // logging and assertions; // // this should NOT be modified by user!!! // // in order to enable/disable library/application logging, // // run tpie configure script with appropriate options // // <><><><><><><><><><><><><><><><><><><><><><><><><><><><><><> // // Use logs if requested. #if TP_LOG_APPS #define TPL_LOGGING 1 #endif #include // Enable assertions if requested. #if TP_ASSERT_APPS #define DEBUG_ASSERTIONS 1 #endif #include #endif stxxl-1.3.1/containers/test_many_stacks.cpp0000644000175000017500000000216011336736656020755 0ustar andreasandreas/*************************************************************************** * containers/test_many_stacks.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2003 Roman Dementiev * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ //! \example containers/test_many_stacks.cpp //! This is an example of how to use \c stxxl::STACK_GENERATOR class //! to generate an \b external stack type //! with \c stxxl::grow_shrink_stack implementation, \b four blocks per page, //! block size \b 4096 bytes #include int main(int argc, char * argv[]) { typedef stxxl::STACK_GENERATOR::result ext_stack_type; if (argc < 2) { STXXL_MSG("Usage: " << argv[0] << " number_of_stacks"); return -1; } ext_stack_type * my_stacks = new ext_stack_type[atoi(argv[1])]; delete[] my_stacks; return 0; } stxxl-1.3.1/containers/test_map_random.cpp0000644000175000017500000002766011031437521020547 0ustar andreasandreas/*************************************************************************** * containers/test_map_random.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2004, 2005 Thomas Nowak * Copyright (C) 2005, 2006 Roman Dementiev * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ //! \file containers/test_map_random.cpp //! \brief File for testing functionality of stxxl::map. //! \example containers/test_map_random.cpp //! This is an example of use of \c stxxl::map container. #include #include "map_test_handlers.h" typedef int key_type; typedef int data_type; struct cmp2 : public std::less { static int max_value() { return (std::numeric_limits::max)(); } }; #define DATA_NODE_BLOCK_SIZE (4096) #define DATA_LEAF_BLOCK_SIZE (4096) typedef std::map std_map_type; typedef stxxl::map xxl_map_type; #define PERCENT_CLEAR 1 #define PERCENT_ERASE_BULK 9 #define PERCENT_ERASE_KEY 90 #define PERCENT_ERASE_ITERATOR 100 #define PERCENT_INSERT_PAIR 100 #define PERCENT_INSERT_BULK 100 #define PERCENT_SIZING 100 #define PERCENT_LOWER 100 #define PERCENT_UPPER 200 #define PERCENT_FIND 100 #define PERCENT_ITERATOR 100 //#define MAX_KEY 1000 #define MAX_KEY 10000 //#define MAX_STEP 0x0001000 #define NODE_BLOCK_SIZE xxl_map_type::node_block_type::raw_size #define LEAF_BLOCK_SIZE xxl_map_type::leaf_block_type::raw_size #define NODE_MELEMENTS xxl_map_type::node_block_type::size #define LEAF_MELEMENTS xxl_map_type::leaf_block_type::size int main(int argc, char * argv[]) { #ifdef NDEBUG STXXL_MSG("Program is compiled with NDEBUG option, which makes the testing wrong."); return 1; #endif typedef std::vector > vector_type; STXXL_MSG("Node block size: " << NODE_BLOCK_SIZE << " bytes"); STXXL_MSG("Leaf block size: " << LEAF_BLOCK_SIZE << " bytes"); STXXL_MSG("Node max elements: " << NODE_MELEMENTS); STXXL_MSG("Leaf max elements: " << LEAF_MELEMENTS); stxxl::random_number32 rnd; //stxxl::ran32State = 1141225706; STXXL_MSG("Init random seed: " << stxxl::ran32State); int a = (PERCENT_CLEAR + PERCENT_SIZING + PERCENT_ERASE_BULK + PERCENT_ERASE_KEY + PERCENT_ERASE_ITERATOR + PERCENT_INSERT_PAIR + PERCENT_INSERT_BULK + PERCENT_LOWER + PERCENT_UPPER + PERCENT_FIND + PERCENT_ITERATOR); assert(a == 1000); if (argc < 2) { STXXL_MSG("Usage: " << argv[0] << " STEP "); STXXL_MSG("Note, that STEP must be > 1000"); return -1; } stxxl::uint64 MAX_STEP = atoi(argv[1]); assert(MAX_STEP > 1000); std_map_type stdmap; xxl_map_type xxlmap(NODE_BLOCK_SIZE * 4, LEAF_BLOCK_SIZE * 3); for (stxxl::uint64 i = 0; i < MAX_STEP; i++) { // *************************************************** // A random number is created to determine which kind // of operation we will be called. // *************************************************** long step = rnd() % 1000; int percent = 0; if (i % (MAX_STEP / 1000) == 0) { STXXL_MSG("*****************************************************"); STXXL_MSG("Step=" << i << " (" << (unsigned)stdmap.size() << ")"); } // ********************************************************* // The clear function will be called // ********************************************************* if (step < (percent += PERCENT_CLEAR)) { if ((unsigned)rand() % 1000 < stdmap.size()) { stdmap.clear(); xxlmap.clear(); assert(stdmap.empty()); assert(xxlmap.empty()); } } // ********************************************************* // The size function will be called // ********************************************************* else if (step < (percent += PERCENT_SIZING)) { std_map_type::size_type size1 = stdmap.size(); xxl_map_type::size_type size2 = xxlmap.size(); assert(size1 == size2); } // ********************************************************* // The erase range function will be called // ********************************************************* else if (step < (percent += PERCENT_ERASE_BULK)) { key_type key1 = rand() % MAX_KEY; key_type key2 = rand() % MAX_KEY; if (key1 > key2) { std::swap(key1, key2); } stdmap.erase(stdmap.lower_bound(key1), stdmap.upper_bound(key2)); xxlmap.erase(xxlmap.lower_bound(key1), xxlmap.upper_bound(key2)); assert(stdmap.size() == xxlmap.size()); assert(stdmap.lower_bound(key1) == stdmap.end() || stdmap.lower_bound(key1) == stdmap.upper_bound(key2)); assert(xxlmap.lower_bound(key1) == xxlmap.end() || xxlmap.lower_bound(key1) == xxlmap.upper_bound(key2)); } // ********************************************************* // The erase a key function will be called // ********************************************************* else if (step < (percent += PERCENT_ERASE_KEY)) { key_type key = rnd() % MAX_KEY; stdmap.erase(key); xxlmap.erase(key); assert(stxxl::not_there(stdmap, key)); assert(stxxl::not_there(xxlmap, key)); } // ********************************************************* // The erase function will be called // ********************************************************* else if (step < (percent += PERCENT_ERASE_ITERATOR)) { key_type key = rnd() % MAX_KEY; std_map_type::iterator stditer = stdmap.find(key); xxl_map_type::iterator xxliter = xxlmap.find(key); assert(stxxl::is_end(stdmap, stditer) == is_end(xxlmap, xxliter)); if (stditer != stdmap.end()) stdmap.erase(stditer); if (xxliter != xxlmap.end()) xxlmap.erase(xxliter); assert(stxxl::not_there(stdmap, key)); assert(stxxl::not_there(xxlmap, key)); } // ********************************************************* // The insert function will be called // ********************************************************* else if (step < (percent += PERCENT_INSERT_PAIR)) { key_type key = rnd() % MAX_KEY; stdmap.insert(std::pair(key, 2 * key)); xxlmap.insert(std::pair(key, 2 * key)); assert(stxxl::there(stdmap, key, 2 * key)); assert(stxxl::there(xxlmap, key, 2 * key)); } // ********************************************************* // The bulk insert function will be called // ********************************************************* else if (step < (percent += PERCENT_INSERT_BULK)) { unsigned lower = rnd() % MAX_KEY; unsigned upper = rnd() % MAX_KEY; if (lower > upper) std::swap(lower, upper); vector_type v2(upper - lower); for (unsigned j = 0; j < (unsigned)(upper - lower); j++) { v2[j].first = lower + j; v2[j].second = 2 * v2[j].first; } stdmap.insert(v2.begin(), v2.end()); xxlmap.insert(v2.begin(), v2.end()); for (unsigned i = lower; i < upper; i++) assert(stxxl::there(stdmap, i, 2 * i)); for (unsigned i = lower; i < upper; i++) assert(stxxl::there(xxlmap, i, 2 * i)); } // ********************************************************* // The lower_bound function will be called // ********************************************************* else if (step < (percent += PERCENT_LOWER)) { key_type key1 = rand() % MAX_KEY; key_type key2 = rand() % MAX_KEY; if (key1 > key2) { std::swap(key1, key2); } while (key1 < key2) { std_map_type::iterator stditer = stdmap.lower_bound(key1); xxl_map_type::iterator xxliter = xxlmap.lower_bound(key1); assert(stxxl::is_end(stdmap, stditer) == is_end(xxlmap, xxliter)); if (!stxxl::is_end(stdmap, stditer)) { assert(stxxl::is_same(*(stditer), *(xxliter))); } key1++; } } // ********************************************************* // The upper_bound function will be called // ********************************************************* else if (step < (percent += PERCENT_UPPER)) { key_type key1 = rand() % MAX_KEY; key_type key2 = rand() % MAX_KEY; if (key1 > key2) { std::swap(key1, key2); } while (key1 < key2) { std_map_type::iterator stditer = stdmap.upper_bound(key1); xxl_map_type::iterator xxliter = xxlmap.upper_bound(key1); assert(stxxl::is_end(stdmap, stditer) == is_end(xxlmap, xxliter)); if (!stxxl::is_end(stdmap, stditer)) { assert(stxxl::is_same(*(stditer), *(xxliter))); } key1++; } } // ********************************************************* // The find function will be called // ********************************************************* else if (step < (percent += PERCENT_FIND)) { key_type key1 = rand() % MAX_KEY; key_type key2 = rand() % MAX_KEY; if (key1 > key2) { std::swap(key1, key2); } while (key1 < key2) { std_map_type::iterator stditer = stdmap.find(key1); xxl_map_type::iterator xxliter = xxlmap.find(key1); assert(stxxl::is_end(stdmap, stditer) == stxxl::is_end(xxlmap, xxliter)); if (!stxxl::is_end(stdmap, stditer)) { assert(stxxl::is_same(*(stditer), *(xxliter))); } key1++; } } // ********************************************************* // The iterate functions will be called // ********************************************************* else if (step < (percent += PERCENT_ITERATOR)) { std_map_type::const_iterator siter1 = stdmap.begin(); xxl_map_type::const_iterator xiter1 = xxlmap.begin(); std_map_type::const_iterator siter2 = siter1; xxl_map_type::const_iterator xiter2 = xiter1; while (siter1 != stdmap.end()) { assert(xiter1 != xxlmap.end()); assert(stxxl::is_same(*(siter1++), *(xiter1++))); if (siter1 != stdmap.end()) { assert(!stxxl::is_same(*siter1, *siter2)); } if (xiter1 != xxlmap.end()) { assert(!stxxl::is_same(*xiter1, *xiter2)); } } assert(xiter1 == xxlmap.end()); assert(siter2 == stdmap.begin()); assert(xiter2 == xxlmap.begin()); } } return 0; } stxxl-1.3.1/containers/leda_sm_pq_benchmark.cpp0000644000175000017500000001413711032661647021515 0ustar andreasandreas/*************************************************************************** * containers/leda_sm_pq_benchmark.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2006 Roman Dementiev * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ //! \example containers/leda_sm_pq_benchmark.cpp //! This is a benchmark mentioned in the paper //! R. Dementiev, L. Kettner, P. Sanders "STXXL: standard template library for XXL data sets" //! Software: Practice and Experience //! Volume 38, Issue 6, Pages 589-637, May 2008 //! DOI: 10.1002/spe.844 #include #include #include #include #include #include #include #include #include #include #include #include #include #define STXXL_MSG(x) \ { std::cout << "[STXXL-MSG] " << x << std::endl << std::flush; \ } #define PQ_MEM_SIZE (512 * 1024 * 1024) #define MAX_ELEMENTS (2000 * 1024 * 1024) struct my_record { int key; int data; my_record() { } my_record(int k, int d) : key(k), data(d) { } }; std::ostream & operator << (std::ostream & o, const my_record & obj) { o << obj.key << " " << obj.data; return o; } bool operator == (const my_record & a, const my_record & b) { return a.key == b.key; } bool operator != (const my_record & a, const my_record & b) { return a.key != b.key; } bool operator < (const my_record & a, const my_record & b) { return a.key < b.key; } bool operator > (const my_record & a, const my_record & b) { return a.key > b.key; } int compare(const my_record & a, const my_record & b) { if (a.key != b.key) return (a.key - b.key); return (a.key - b.key); } #define BLOCK_SIZE1 (EXT_BLK_SZ * 4) #define BLOCK_SIZE2 (DISK_BLOCK_SIZE * 4) #if 1 unsigned ran32State = 0xdeadbeef; inline int myrand() { return ((int)((ran32State = 1664525 * ran32State + 1013904223) >> 1)) - 1; } #else // a longer pseudo random sequence long long unsigned ran32State = 0xdeadbeef; inline long long unsigned myrand() { return (ran32State = (ran32State * 0x5DEECE66DULL + 0xBULL) & 0xFFFFFFFFFFFFULL); } #endif int pq_blocks; void run_ledasm_insert_all_delete_all(stxxl::int64 ops) { array_heap PQ(pq_blocks); stxxl::int64 i; //my_record cur; stxxl::timer Timer; Timer.start(); for (i = 0; i < ops; ++i) { PQ.insert(myrand(), 0); } Timer.stop(); STXXL_MSG("Records in PQ: " << PQ.size()); if (i != PQ.size()) { STXXL_MSG("Size does not match"); abort(); } STXXL_MSG("Insertions elapsed time: " << (Timer.mseconds() / 1000.) << " seconds : " << (double(ops) / (Timer.mseconds() / 1000.)) << " key/data pairs per sec"); ext_mem_mgr.print_statistics(); ext_mem_mgr.reset_statistics(); //////////////////////////////////////////////// Timer.reset(); for (i = 0; i < ops; ++i) { PQ.del_min(); } Timer.stop(); STXXL_MSG("Records in PQ: " << PQ.size()); if (!PQ.empty()) { STXXL_MSG("PQ must be empty"); abort(); } STXXL_MSG("Deletions elapsed time: " << (Timer.mseconds() / 1000.) << " seconds : " << (double(ops) / (Timer.mseconds() / 1000.)) << " key/data pairs per sec"); ext_mem_mgr.print_statistics(); } void run_ledasm_intermixed(stxxl::int64 ops) { array_heap PQ(pq_blocks); stxxl::int64 i; //my_record cur; stxxl::timer Timer; Timer.start(); for (i = 0; i < ops; ++i) { PQ.insert(myrand(), 0); } Timer.stop(); STXXL_MSG("Records in PQ: " << PQ.size()); if (i != PQ.size()) { STXXL_MSG("Size does not match"); abort(); } STXXL_MSG("Insertions elapsed time: " << (Timer.mseconds() / 1000.) << " seconds : " << (double(ops) / (Timer.mseconds() / 1000.)) << " key/data pairs per sec"); ext_mem_mgr.print_statistics(); ext_mem_mgr.reset_statistics(); //////////////////////////////////////////////// Timer.reset(); for (i = 0; i < ops; ++i) { int o = myrand() % 3; if (o == 0) { PQ.insert(myrand(), 0); } else { assert(!PQ.empty()); PQ.del_min(); } } Timer.stop(); STXXL_MSG("Records in PQ: " << PQ.size()); STXXL_MSG("Deletions/Insertion elapsed time: " << (Timer.mseconds() / 1000.) << " seconds : " << (double(ops) / (Timer.mseconds() / 1000.)) << " key/data pairs per sec"); ext_mem_mgr.print_statistics(); } int main(int argc, char * argv[]) { STXXL_MSG("block size 1: " << BLOCK_SIZE1 << " bytes"); STXXL_MSG("block size 2: " << BLOCK_SIZE2 << " bytes"); if (argc < 3) { STXXL_MSG("Usage: " << argv[0] << " version #ops"); STXXL_MSG("\t version = 1: insert-all-delete-all leda-sm pqueue"); STXXL_MSG("\t version = 2: insert-all-delete-all leda-sm pqueue"); return -1; } int version = atoi(argv[1]); stxxl::int64 ops = atoll(argv[2]); if (ops > MAX_ELEMENTS) { STXXL_MSG("#ops can not be larger than " << MAX_ELEMENTS); return 0; } pq_blocks = PQ_MEM_SIZE / (EXT_BLK_SZ * sizeof(GenPtr)); if (pq_blocks <= 500) { std::cout << "Array heap must have > 500 blocks, current number of blocks " << pq_blocks << std::endl; return -1; } STXXL_MSG("Running version : " << version); STXXL_MSG("Operations to perform: " << ops); switch (version) { case 1: run_ledasm_insert_all_delete_all(ops); break; case 2: run_ledasm_intermixed(ops); break; default: STXXL_MSG("Unsupported version " << version); } } stxxl-1.3.1/containers/berkeley_db_benchmark.cpp0000644000175000017500000010754711535151017021661 0ustar andreasandreas/*************************************************************************** * containers/berkeley_db_benchmark.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2006 Roman Dementiev * Copyright (C) 2009, 2010 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ //! \example containers/berkeley_db_benchmark.cpp //! This is a benchmark mentioned in the paper //! R. Dementiev, L. Kettner, P. Sanders "STXXL: standard template library for XXL data sets" //! Software: Practice and Experience //! Volume 38, Issue 6, Pages 589-637, May 2008 //! DOI: 10.1002/spe.844 #include #include #include #include ///// BDB header //////////// #include ///////// TPIE headers ////////// #include "app_config.h" #include #include //////////////////////////// #define BDB_BULK_SCAN #define KEY_SIZE 8 #define DATA_SIZE 32 #define NODE_BLOCK_SIZE (32 * 1024) #define LEAF_BLOCK_SIZE (32 * 1024) #define LEAF_BLOCK_SIZE (32 * 1024) #define TOTAL_CACHE_SIZE (750 * 1024 * 1024) //#define TOTAL_CACHE_SIZE (150 * 1024 * 1024) //#define NODE_CACHE_SIZE (1 * (TOTAL_CACHE_SIZE / 40)) //#define LEAF_CACHE_SIZE (39 * (TOTAL_CACHE_SIZE / 40)) #define NODE_CACHE_SIZE (64 * 1024 * 1024) #define LEAF_CACHE_SIZE (TOTAL_CACHE_SIZE - NODE_CACHE_SIZE) #define SORTER_MEM (TOTAL_CACHE_SIZE - 1024 * 1024 * 2 * 4) #define SCAN_LIMIT(x) (x) //#define BDB_FILE "/data3/bdb_file" #define BDB_FILE "/var/tmp/bdb_file" // BDB settings u_int32_t pagesize = LEAF_BLOCK_SIZE; u_int bulkbufsize = 4 * 1024 * 1024; u_int logbufsize = 8 * 1024 * 1024; u_int cachesize = (TOTAL_CACHE_SIZE < 500 * 1024 * 1024) ? (4 * (TOTAL_CACHE_SIZE / 5)) : (TOTAL_CACHE_SIZE - 100 * 1024 * 1024); u_int datasize = DATA_SIZE; u_int keysize = KEY_SIZE; u_int numitems = 0; const char * letters = "abcdefghijklmnopqrstuvwxuz"; struct my_key { char keybuf[KEY_SIZE]; }; std::ostream & operator << (std::ostream & o, const my_key & obj) { for (int i = 0; i < KEY_SIZE; ++i) o << obj.keybuf[i]; return o; } bool operator == (const my_key & a, const my_key & b) { return strncmp(a.keybuf, b.keybuf, KEY_SIZE) == 0; } bool operator != (const my_key & a, const my_key & b) { return strncmp(a.keybuf, b.keybuf, KEY_SIZE) != 0; } bool operator < (const my_key & a, const my_key & b) { return strncmp(a.keybuf, b.keybuf, KEY_SIZE) < 0; } bool operator > (const my_key & a, const my_key & b) { return strncmp(a.keybuf, b.keybuf, KEY_SIZE) > 0; } bool operator <= (const my_key & a, const my_key & b) { return strncmp(a.keybuf, b.keybuf, KEY_SIZE) <= 0; } bool operator >= (const my_key & a, const my_key & b) { return strncmp(a.keybuf, b.keybuf, KEY_SIZE) >= 0; } struct my_data { char databuf[DATA_SIZE]; }; std::ostream & operator << (std::ostream & o, const my_data & obj) { o << "DATA(size=" << sizeof(obj) << ") "; return o; } my_key min_key, max_key; struct comp_type : std::binary_function { bool operator () (const my_key & a, const my_key & b) const { return strncmp(a.keybuf, b.keybuf, KEY_SIZE) < 0; } static my_key max_value() { return max_key; } static my_key min_value() { return min_key; } }; /// TPIE declarations // Key type. typedef my_key bkey_t; // Element type for the btree. struct el_t { bkey_t key_; my_data data_; el_t(bkey_t k) : key_(k) { } el_t() { } }; struct key_from_el { bkey_t operator () (const el_t & v) const { return v.key_; } }; // Temporary distinction btw UN*X and WIN, since there are some // problems with the MMAP collection implementation. #ifdef _WIN32 typedef AMI_btree, key_from_el, BTE_COLLECTION_UFS> u_btree_t; #else typedef AMI_btree, key_from_el> u_btree_t; #endif void init() { memset(max_key.keybuf, (std::numeric_limits::max)(), KEY_SIZE); memset(min_key.keybuf, (std::numeric_limits::min)(), KEY_SIZE); } typedef stxxl::map map_type; #define REAL_NODE_BLOCK_SIZE map_type::node_block_type::raw_size #define REAL_LEAF_BLOCK_SIZE map_type::leaf_block_type::raw_size #define REAL_NODE_MELEMENTS map_type::node_block_type::size #define REAL_LEAF_MELEMENTS map_type::leaf_block_type::size typedef stxxl::VECTOR_GENERATOR, 1, 1>::result vector_type; //typedef stxxl::vector,1,stxxl::lru_pager<1>,512*1024> vector_type; //#define KEYPOS (i % KEY_SIZE) //#define VALUE (myrand() % 26) #if 0 unsigned ran32State = 0xdeadbeef; inline unsigned myrand() { return (ran32State = 1664525 * ran32State + 1013904223); } inline void rand_key(stxxl::int64 pos, my_key & Key) { for (int i = 0; i < KEY_SIZE; ++i) Key.keybuf[i] = letters[myrand() % 26]; } #else // a longer pseudo random sequence long long unsigned ran32State = 0xdeadbeef; inline long long unsigned myrand() { return (ran32State = (ran32State * 0x5DEECE66DULL + 0xBULL) & 0xFFFFFFFFFFFFULL); } inline void rand_key(stxxl::int64 /*pos*/, my_key & Key) { long long unsigned r = myrand(); for (int i = 0; i < KEY_SIZE; ++i) { Key.keybuf[i] = letters[r % 26]; r >>= 5; } } #endif void run_bdb_btree(stxxl::int64 ops) { const char * filename = BDB_FILE; my_key key1_storage; my_data data1_storage; unlink(filename); memset(key1_storage.keybuf, 'a', KEY_SIZE); memset(data1_storage.databuf, 'b', DATA_SIZE); Db db(NULL, 0); // Instantiate the Db object try { db.set_errfile(stderr); db.set_pagesize(pagesize); db.set_cachesize(0, cachesize, 1); // Open the database db.open(NULL, // Transaction pointer filename, // Database file name NULL, // Optional logical database name DB_BTREE, // Database access method DB_CREATE, // Open flags 0); // File mode (using defaults) // here we start with the tests Dbt key1(key1_storage.keybuf, KEY_SIZE); Dbt data1(data1_storage.databuf, DATA_SIZE); stxxl::timer Timer; stxxl::int64 n_inserts = ops, n_locates = ops, n_range_queries = ops, n_deletes = ops; stxxl::int64 i; //comp_type cmp_; ran32State = 0xdeadbeef; DB_BTREE_STAT * dbstat; db.stat(NULL, &dbstat, 0); STXXL_MSG("Records in map: " << dbstat->bt_ndata); db.get_env()->memp_stat(NULL, NULL, DB_STAT_CLEAR); Timer.start(); for (i = 0; i < n_inserts; ++i) { //key1_storage.keybuf[KEYPOS] = letters[VALUE]; rand_key(i, key1_storage); db.put(NULL, &key1, &data1, DB_NOOVERWRITE); } Timer.stop(); db.stat(NULL, &dbstat, 0); STXXL_MSG("Records in map: " << dbstat->bt_ndata); STXXL_MSG("Insertions elapsed time: " << (Timer.mseconds() / 1000.) << " seconds : " << (double(n_inserts) / (Timer.mseconds() / 1000.)) << " key/data pairs per sec"); db.get_env()->memp_stat_print(DB_STAT_CLEAR); ///////////////////////////////////////// Timer.reset(); Timer.start(); Dbc * cursorp; db.cursor(NULL, &cursorp, 0); for (i = 0; i < n_locates; ++i) { //key1_storage.keybuf[KEYPOS] = letters[VALUE]; rand_key(i, key1_storage); Dbt keyx(key1_storage.keybuf, KEY_SIZE); Dbt datax(data1_storage.databuf, DATA_SIZE); cursorp->get(&keyx, &datax, DB_SET_RANGE); } Timer.stop(); STXXL_MSG("Locates elapsed time: " << (Timer.mseconds() / 1000.) << " seconds : " << (double(ops) / (Timer.mseconds() / 1000.)) << " key/data pairs per sec"); db.get_env()->memp_stat_print(DB_STAT_CLEAR); //////////////////////////////////// Timer.reset(); Timer.start(); stxxl::int64 n_scanned = 0; for (i = 0; i < n_range_queries; ++i) { //key1_storage.keybuf[KEYPOS] = letters[VALUE]; rand_key(i, key1_storage); my_key last_key = key1_storage; //key1_storage.keybuf[KEYPOS] = letters[VALUE]; rand_key(i, key1_storage); if (last_key < key1_storage) std::swap(last_key, key1_storage); Dbt keyx(key1_storage.keybuf, KEY_SIZE); Dbt datax(data1_storage.databuf, DATA_SIZE); if (cursorp->get(&keyx, &datax, DB_SET_RANGE) == DB_NOTFOUND) continue; while (*((my_key *)keyx.get_data()) <= last_key) { ++n_scanned; if (cursorp->get(&keyx, &datax, DB_NEXT) == DB_NOTFOUND) break; } if (n_scanned >= 10 * n_range_queries) { ++i; break; } } n_range_queries = i; Timer.stop(); if (cursorp != NULL) cursorp->close(); STXXL_MSG("Range query elapsed time: " << (Timer.mseconds() / 1000.) << " seconds : " << (double(n_scanned) / (Timer.mseconds() / 1000.)) << " key/data pairs per sec, #queries " << n_range_queries << " #scanned elements: " << n_scanned); db.get_env()->memp_stat_print(DB_STAT_CLEAR); ////////////////////////////////////// ran32State = 0xdeadbeef; memset(key1_storage.keybuf, 'a', KEY_SIZE); Timer.reset(); Timer.start(); for (i = 0; i < n_deletes; ++i) { //key1_storage.keybuf[KEYPOS] = letters[VALUE]; rand_key(i, key1_storage); Dbt keyx(key1_storage.keybuf, KEY_SIZE); db.del(NULL, &keyx, 0); } Timer.stop(); db.stat(NULL, &dbstat, 0); STXXL_MSG("Records in map: " << dbstat->bt_ndata); STXXL_MSG("Erase elapsed time: " << (Timer.mseconds() / 1000.) << " seconds : " << (double(ops) / (Timer.mseconds() / 1000.)) << " key/data pairs per sec"); db.get_env()->memp_stat_print(DB_STAT_CLEAR); db.close(0); } catch (DbException & e) { STXXL_ERRMSG("DbException happened"); } catch (std::exception & e) { STXXL_ERRMSG("std::exception happened"); } unlink(filename); } void run_stxxl_map(stxxl::int64 ops) { map_type Map(NODE_CACHE_SIZE, LEAF_CACHE_SIZE); Map.enable_prefetching(); stxxl::stats * Stats = stxxl::stats::get_instance(); std::pair element; memset(element.first.keybuf, 'a', KEY_SIZE); memset(element.second.databuf, 'b', DATA_SIZE); stxxl::timer Timer; stxxl::int64 n_inserts = ops, n_locates = ops, n_range_queries = ops, n_deletes = ops; stxxl::int64 i; //comp_type cmp_; ran32State = 0xdeadbeef; //stxxl::random_number32 myrand; STXXL_MSG("Records in map: " << Map.size()); stxxl::stats_data stats_begin(*Stats); Timer.start(); for (i = 0; i < n_inserts; ++i) { //element.first.keybuf[KEYPOS] = letters[VALUE]; rand_key(i, element.first); Map.insert(element); } Timer.stop(); STXXL_MSG("Records in map: " << Map.size()); STXXL_MSG("Insertions elapsed time: " << (Timer.mseconds() / 1000.) << " seconds : " << (double(n_inserts) / (Timer.mseconds() / 1000.)) << " key/data pairs per sec"); std::cout << (stxxl::stats_data(*Stats) - stats_begin); //////////////////////////////////////////////// const map_type & CMap(Map); // const map reference stats_begin = stxxl::stats_data(*Stats); Timer.reset(); Timer.start(); for (i = 0; i < n_locates; ++i) { //element.first.keybuf[KEYPOS] = letters[VALUE]; rand_key(i, element.first); CMap.lower_bound(element.first); } Timer.stop(); STXXL_MSG("Locates elapsed time: " << (Timer.mseconds() / 1000.) << " seconds : " << (double(n_locates) / (Timer.mseconds() / 1000.)) << " key/data pairs per sec"); std::cout << (stxxl::stats_data(*Stats) - stats_begin); //////////////////////////////////// stats_begin = stxxl::stats_data(*Stats); Timer.reset(); Timer.start(); stxxl::int64 n_scanned = 0; //, skipped_qieries = 0; for (i = 0; i < n_range_queries; ++i) { //element.first.keybuf[KEYPOS] = letters[VALUE]; rand_key(i, element.first); my_key begin_key = element.first; map_type::const_iterator begin = CMap.lower_bound(element.first); //element.first.keybuf[KEYPOS] = letters[VALUE]; rand_key(i, element.first); map_type::const_iterator beyond = CMap.lower_bound(element.first); if (element.first < begin_key) std::swap(begin, beyond); while (begin != beyond) { my_data tmp = begin->second; stxxl::STXXL_UNUSED(tmp); ++n_scanned; ++begin; } if (n_scanned >= 10 * n_range_queries) { ++i; break; } } n_range_queries = i; Timer.stop(); STXXL_MSG("Range query elapsed time: " << (Timer.mseconds() / 1000.) << " seconds : " << (double(n_scanned) / (Timer.mseconds() / 1000.)) << " key/data pairs per sec, #queries " << n_range_queries << " #scanned elements: " << n_scanned); std::cout << (stxxl::stats_data(*Stats) - stats_begin); ////////////////////////////////////// ran32State = 0xdeadbeef; memset(element.first.keybuf, 'a', KEY_SIZE); memset(element.second.databuf, 'b', DATA_SIZE); stats_begin = stxxl::stats_data(*Stats); Timer.reset(); Timer.start(); for (i = 0; i < n_deletes; ++i) { //element.first.keybuf[KEYPOS] = letters[VALUE]; rand_key(i, element.first); Map.erase(element.first); } Timer.stop(); STXXL_MSG("Records in map: " << Map.size()); STXXL_MSG("Erase elapsed time: " << (Timer.mseconds() / 1000.) << " seconds : " << (double(n_deletes) / (Timer.mseconds() / 1000.)) << " key/data pairs per sec"); std::cout << (stxxl::stats_data(*Stats) - stats_begin); } class rand_key_gen { stxxl::int64 counter; my_key & current; stxxl::random_number32 myrand; rand_key_gen(); public: typedef my_key value_type; rand_key_gen(stxxl::int64 el, my_key & cur) : counter(el), current(cur) { //const stxxl::int64 & i = counter; //current.keybuf[KEYPOS] = letters[VALUE]; rand_key(counter, current); } const my_key & operator * () { return current; } const my_key * operator -> () { return ¤t; } rand_key_gen & operator ++ () { --counter; //const stxxl::int64 & i = counter; //current.keybuf[KEYPOS] = letters[VALUE]; rand_key(counter, current); return *this; } bool empty() const { return counter == 0; } }; template class key2pair { InputType & in; std::pair current; key2pair(); public: typedef std::pair value_type; key2pair(InputType & in_) : in(in_) { if (!in.empty()) current.first = *in; } const value_type & operator * () { return current; } const value_type * operator -> () { return ¤t; } key2pair & operator ++ () { ++in; if (!empty()) current.first = *in; return *this; } bool empty() const { return in.empty(); } }; void run_stxxl_map_big(stxxl::int64 n, unsigned ops) { stxxl::stats * Stats = stxxl::stats::get_instance(); std::pair element; memset(element.first.keybuf, 'a', KEY_SIZE); memset(element.second.databuf, 'b', DATA_SIZE); stxxl::timer Timer; stxxl::int64 n_inserts = ops, n_locates = ops, n_range_queries = ops, n_deletes = ops; stxxl::int64 i; //comp_type cmp_; ran32State = 0xdeadbeef; //stxxl::random_number32 myrand; Timer.start(); vector_type SortedSeq(n); const vector_type & CSortedSeq(SortedSeq); { rand_key_gen Gen(n, element.first); typedef stxxl::stream::sort sorter_type; sorter_type Sorter(Gen, comp_type(), SORTER_MEM); typedef key2pair key2pair_type; key2pair_type Key2Pair(Sorter); stxxl::stream::materialize(Key2Pair, SortedSeq.begin()); } Timer.stop(); STXXL_MSG("Finished sorting input. Elapsed time: " << (Timer.mseconds() / 1000.) << " seconds."); stxxl::stats_data stats_begin(*Stats); Timer.reset(); Timer.start(); // bulk construction map_type Map(CSortedSeq.begin(), CSortedSeq.end(), NODE_CACHE_SIZE, LEAF_CACHE_SIZE, true); Timer.stop(); STXXL_MSG("Records in map: " << Map.size()); STXXL_MSG("Construction elapsed time: " << (Timer.mseconds() / 1000.) << " seconds : " << (double(n) / (Timer.mseconds() / 1000.)) << " key/data pairs per sec"); Map.print_statistics(cout); Map.reset_statistics(); std::cout << (stxxl::stats_data(*Stats) - stats_begin); //////////////////////////////////////// Map.disable_prefetching(); stats_begin = stxxl::stats_data(*Stats); Timer.reset(); Timer.start(); for (i = 0; i < n_inserts; ++i) { //element.first.keybuf[KEYPOS] = letters[VALUE]; rand_key(i, element.first); Map.insert(element); } Timer.stop(); STXXL_MSG("Records in map: " << Map.size()); STXXL_MSG("Insertions elapsed time: " << (Timer.mseconds() / 1000.) << " seconds : " << (double(n_inserts) / (Timer.mseconds() / 1000.)) << " key/data pairs per sec"); Map.print_statistics(cout); Map.reset_statistics(); std::cout << (stxxl::stats_data(*Stats) - stats_begin); //////////////////////////////////// const map_type & CMap(Map); // const map reference Timer.reset(); Timer.start(); for (i = 0; i < n_locates; ++i) { //element.first.keybuf[KEYPOS] = letters[VALUE]; rand_key(i, element.first); CMap.lower_bound(element.first); } Timer.stop(); STXXL_MSG("Locates elapsed time: " << (Timer.mseconds() / 1000.) << " seconds : " << (double(ops) / (Timer.mseconds() / 1000.)) << " key/data pairs per sec"); Map.print_statistics(cout); Map.reset_statistics(); std::cout << (stxxl::stats_data(*Stats) - stats_begin); //////////////////////////////////// Map.enable_prefetching(); stats_begin = stxxl::stats_data(*Stats); Timer.reset(); Timer.start(); stxxl::int64 n_scanned = 0; //, skipped_qieries = 0; for (i = 0; i < n_range_queries; ++i) { //element.first.keybuf[KEYPOS] = letters[VALUE]; rand_key(i, element.first); my_key begin_key = element.first; map_type::const_iterator begin = CMap.lower_bound(element.first); //element.first.keybuf[KEYPOS] = letters[VALUE]; rand_key(i, element.first); map_type::const_iterator beyond = CMap.lower_bound(element.first); if (element.first < begin_key) std::swap(begin, beyond); /* STXXL_MSG("Looking "<begin_key)?element.first:begin_key)); }*/ while (begin != beyond) { ++n_scanned; ++begin; } if (n_scanned >= SCAN_LIMIT(n)) { ++i; break; } } n_range_queries = i; Timer.stop(); STXXL_MSG("Range query elapsed time: " << (Timer.mseconds() / 1000.) << " seconds : " << (double(n_scanned) / (Timer.mseconds() / 1000.)) << " key/data pairs per sec, #queries " << n_range_queries << " #scanned elements: " << n_scanned); Map.print_statistics(cout); Map.reset_statistics(); std::cout << (stxxl::stats_data(*Stats) - stats_begin); ////////////////////////////////////// ran32State = 0xdeadbeef; memset(element.first.keybuf, 'a', KEY_SIZE); memset(element.second.databuf, 'b', DATA_SIZE); Map.disable_prefetching(); stats_begin = stxxl::stats_data(*Stats); Timer.reset(); Timer.start(); for (i = n_deletes; i > 0; --i) { //element.first.keybuf[KEYPOS] = letters[VALUE]; rand_key(i, element.first); Map.erase(element.first); } Timer.stop(); STXXL_MSG("Records in map: " << Map.size()); STXXL_MSG("Erase elapsed time: " << (Timer.mseconds() / 1000.) << " seconds : " << (double(ops) / (Timer.mseconds() / 1000.)) << " key/data pairs per sec"); Map.print_statistics(cout); Map.reset_statistics(); std::cout << (stxxl::stats_data(*Stats) - stats_begin); } ///////////////////////////////////////////////////////////////////////// typedef AMI_STREAM stream_t; char dummy; class MyFilter { public: bool operator () (const el_t & v) const { dummy += v.key_.keybuf[0]; // touch element return true; } }; void run_tpie_btree_big(stxxl::int64 n, unsigned ops) { el_t element; memset(element.key_.keybuf, 'a', KEY_SIZE); memset(element.data_.databuf, 'b', DATA_SIZE); // Log debugging info from the application, but not from the library. tpie_log_init(TPIE_LOG_APP_DEBUG); MM_manager.set_memory_limit(TOTAL_CACHE_SIZE); MM_manager.enforce_memory_limit(); stream_t * is = new stream_t; stxxl::timer Timer; stxxl::int64 n_inserts = ops, n_locates = ops, n_range_queries = ops, n_deletes = ops; stxxl::int64 i; //comp_type cmp_; ran32State = 0xdeadbeef; //stxxl::random_number32 myrand; Timer.start(); { rand_key_gen Gen(n, element.key_); typedef stxxl::stream::sort sorter_type; sorter_type Sorter(Gen, comp_type(), SORTER_MEM); //typedef key2pair key2pair_type; //key2pair_type Key2Pair(Sorter); while (!Sorter.empty()) { is->write_item(*Sorter); ++Sorter; } } Timer.stop(); STXXL_MSG("Finished sorting input. Elapsed time: " << (Timer.mseconds() / 1000.) << " seconds."); Timer.reset(); Timer.start(); // bulk construction u_btree_t * u_btree; AMI_btree_params params; params.node_block_factor = NODE_BLOCK_SIZE / 4096; params.leaf_block_factor = LEAF_BLOCK_SIZE / 4096; params.leaf_cache_size = LEAF_CACHE_SIZE / LEAF_BLOCK_SIZE; params.node_cache_size = NODE_CACHE_SIZE / NODE_BLOCK_SIZE; u_btree = new u_btree_t(params); using std::cout; using std::cerr; if (!u_btree->is_valid()) { cerr << "Error initializing btree. Aborting.\n"; delete u_btree; exit(1); } if (u_btree->load_sorted(is, 1.0, 1.0) != AMI_ERROR_NO_ERROR) cerr << "Error during bulk loading.\n"; Timer.stop(); STXXL_MSG("Records in map: " << u_btree->size()); STXXL_MSG("Construction elapsed time: " << (Timer.mseconds() / 1000.) << " seconds : " << (double(n) / (Timer.mseconds() / 1000.)) << " key/data pairs per sec"); //////////////////////////////////////// Timer.reset(); Timer.start(); for (i = 0; i < n_inserts; ++i) { //element.first.keybuf[KEYPOS] = letters[VALUE]; rand_key(i, element.key_); u_btree->insert(element); } Timer.stop(); STXXL_MSG("Records in map: " << u_btree->size()); STXXL_MSG("Insertions elapsed time: " << (Timer.mseconds() / 1000.) << " seconds : " << (double(n_inserts) / (Timer.mseconds() / 1000.)) << " key/data pairs per sec"); //////////////////////////////////////////////// Timer.reset(); Timer.start(); el_t result; for (i = 0; i < n_locates; ++i) { //element.first.keybuf[KEYPOS] = letters[VALUE]; rand_key(i, element.key_); u_btree->succ(element.key_, result); } Timer.stop(); STXXL_MSG("Locates elapsed time: " << (Timer.mseconds() / 1000.) << " seconds : " << (double(ops) / (Timer.mseconds() / 1000.)) << " key/data pairs per sec"); //////////////////////////////////// Timer.reset(); Timer.start(); stxxl::int64 n_scanned = 0; //, skipped_qieries = 0; MyFilter filter; for (i = 0; i < n_range_queries; ++i) { rand_key(i, element.key_); my_key begin_key = element.key_; rand_key(i, element.key_); if (element.key_ < begin_key) n_scanned += u_btree->range_query(element.key_, begin_key, NULL, filter); else n_scanned += u_btree->range_query(begin_key, element.key_, NULL, filter); if (n_scanned >= SCAN_LIMIT(n)) { ++i; break; } } n_range_queries = i; Timer.stop(); STXXL_MSG("Range query elapsed time: " << (Timer.mseconds() / 1000.) << " seconds : " << (double(n_scanned) / (Timer.mseconds() / 1000.)) << " key/data pairs per sec, #queries " << n_range_queries << " #scanned elements: " << n_scanned); ////////////////////////////////////// ran32State = 0xdeadbeef; memset(element.key_.keybuf, 'a', KEY_SIZE); memset(element.data_.databuf, 'b', DATA_SIZE); Timer.reset(); Timer.start(); for (i = n_deletes; i > 0; --i) { //element.first.keybuf[KEYPOS] = letters[VALUE]; rand_key(i, element.key_); u_btree->erase(element.key_); } Timer.stop(); STXXL_MSG("Records in map: " << u_btree->size()); STXXL_MSG("Erase elapsed time: " << (Timer.mseconds() / 1000.) << " seconds : " << (double(ops) / (Timer.mseconds() / 1000.)) << " key/data pairs per sec"); delete u_btree; delete is; } void run_bdb_btree_big(stxxl::int64 n, unsigned ops) { const char * filename = BDB_FILE; my_key key1_storage; my_data data1_storage; #ifdef BDB_BULK_SCAN int * bulk_buffer = new int[logbufsize / sizeof(int)]; #endif unlink(filename); memset(key1_storage.keybuf, 'a', KEY_SIZE); memset(data1_storage.databuf, 'b', DATA_SIZE); Db db(NULL, 0); // Instantiate the Db object try { // here we start with the tests Dbt key1(key1_storage.keybuf, KEY_SIZE); Dbt data1(data1_storage.databuf, DATA_SIZE); stxxl::timer Timer; stxxl::int64 n_inserts = ops, n_locates = ops, n_range_queries = ops, n_deletes = ops; stxxl::int64 i; //comp_type cmp_; ran32State = 0xdeadbeef; Timer.start(); vector_type SortedSeq(n); //const vector_type & CSortedSeq(SortedSeq); { rand_key_gen Gen(n, key1_storage); typedef stxxl::stream::sort sorter_type; sorter_type Sorter(Gen, comp_type(), SORTER_MEM); typedef key2pair key2pair_type; key2pair_type Key2Pair(Sorter); stxxl::stream::materialize(Key2Pair, SortedSeq.begin()); } Timer.stop(); STXXL_MSG("Finished sorting input. Elapsed time: " << (Timer.mseconds() / 1000.) << " seconds."); db.set_errfile(stderr); db.set_pagesize(pagesize); db.set_cachesize(0, cachesize, 10); STXXL_MSG("BDB cache size set."); // Open the database db.open(NULL, // Transaction pointer filename, // Database file name NULL, // Optional logical database name DB_BTREE, // Database access method DB_CREATE, // Open flags 0); // File mode (using defaults) db.get_env()->memp_stat(NULL, NULL, DB_STAT_CLEAR); Timer.reset(); Timer.start(); // DBD does not have bulk construction // however inserting in sorted order might help // to improve performance vector_type::const_iterator cit = SortedSeq.begin(); for (i = 0; i < n; ++i, ++cit) { key1_storage = cit->first; db.put(NULL, &key1, &data1, DB_NOOVERWRITE); } Timer.stop(); DB_BTREE_STAT * dbstat; db.stat(NULL, &dbstat, 0); STXXL_MSG("Records in map: " << dbstat->bt_ndata); STXXL_MSG("Construction elapsed time: " << (Timer.mseconds() / 1000.) << " seconds : " << (double(n) / (Timer.mseconds() / 1000.)) << " key/data pairs per sec"); db.stat_print(0); db.get_env()->memp_stat_print(DB_STAT_CLEAR); //////////////////////////////////////// Timer.reset(); Timer.start(); for (i = 0; i < n_inserts; ++i) { //key1_storage.keybuf[KEYPOS] = letters[VALUE]; rand_key(i, key1_storage); db.put(NULL, &key1, &data1, DB_NOOVERWRITE); } Timer.stop(); db.stat(NULL, &dbstat, 0); STXXL_MSG("Records in map: " << dbstat->bt_ndata); STXXL_MSG("Insertions elapsed time: " << (Timer.mseconds() / 1000.) << " seconds : " << (double(n_inserts) / (Timer.mseconds() / 1000.)) << " key/data pairs per sec"); db.stat_print(0); db.get_env()->memp_stat_print(DB_STAT_CLEAR); ///////////////////////////////////////// Timer.reset(); Timer.start(); Dbc * cursorp; db.cursor(NULL, &cursorp, 0); for (i = 0; i < n_locates; ++i) { //key1_storage.keybuf[KEYPOS] = letters[VALUE]; rand_key(i, key1_storage); Dbt keyx(key1_storage.keybuf, KEY_SIZE); Dbt datax(data1_storage.databuf, DATA_SIZE); cursorp->get(&keyx, &datax, DB_SET_RANGE); } Timer.stop(); STXXL_MSG("Locates elapsed time: " << (Timer.mseconds() / 1000.) << " seconds : " << (double(ops) / (Timer.mseconds() / 1000.)) << " key/data pairs per sec"); db.stat_print(0); db.get_env()->memp_stat_print(DB_STAT_CLEAR); //////////////////////////////////// Timer.reset(); Timer.start(); stxxl::int64 n_scanned = 0; for (i = 0; i < n_range_queries; ++i) { //key1_storage.keybuf[KEYPOS] = letters[VALUE]; rand_key(i, key1_storage); my_key last_key = key1_storage; //key1_storage.keybuf[KEYPOS] = letters[VALUE]; rand_key(i, key1_storage); if (last_key < key1_storage) std::swap(last_key, key1_storage); //STXXL_MSG("Looking "<get(&keyx, &datax, DB_SET_RANGE | DB_MULTIPLE_KEY) == DB_NOTFOUND) continue; do { DbMultipleKeyDataIterator BulkIterator(datax); Dbt key1, data1; while (BulkIterator.next(key1, data1) && *((my_key *)key1.get_data()) <= last_key) { ++n_scanned; //STXXL_MSG("Result "<<*((my_key *)key1.get_data())); } if (cursorp->get(&keyx, &datax, DB_NEXT | DB_MULTIPLE_KEY) == DB_NOTFOUND) break; if (*((my_key *)keyx.get_data()) > last_key) { break; } } while (1); #else if (cursorp->get(&keyx, &datax, DB_SET_RANGE) == DB_NOTFOUND) continue; while (*((my_key *)keyx.get_data()) <= last_key) { ++n_scanned; if (cursorp->get(&keyx, &datax, DB_NEXT) == DB_NOTFOUND) break; } #endif if (n_scanned >= SCAN_LIMIT(n)) { ++i; break; } } n_range_queries = i; Timer.stop(); if (cursorp != NULL) cursorp->close(); STXXL_MSG("Range query elapsed time: " << (Timer.mseconds() / 1000.) << " seconds : " << (double(n_scanned) / (Timer.mseconds() / 1000.)) << " key/data pairs per sec, #queries " << n_range_queries << " #scanned elements: " << n_scanned); db.stat_print(0); db.get_env()->memp_stat_print(DB_STAT_CLEAR); ////////////////////////////////////// ran32State = 0xdeadbeef; memset(key1_storage.keybuf, 'a', KEY_SIZE); Timer.reset(); Timer.start(); for (i = 0; i < n_deletes; ++i) { //key1_storage.keybuf[KEYPOS] = letters[VALUE]; rand_key(i, key1_storage); Dbt keyx(key1_storage.keybuf, KEY_SIZE); db.del(NULL, &keyx, 0); } Timer.stop(); db.stat(NULL, &dbstat, 0); STXXL_MSG("Records in map: " << dbstat->bt_ndata); STXXL_MSG("Erase elapsed time: " << (Timer.mseconds() / 1000.) << " seconds : " << (double(ops) / (Timer.mseconds() / 1000.)) << " key/data pairs per sec"); db.stat_print(0); db.get_env()->memp_stat_print(DB_STAT_CLEAR); db.close(0); } catch (DbException & e) { STXXL_ERRMSG("DbException happened"); } catch (std::exception & e) { STXXL_ERRMSG("std::exception happened"); } unlink(filename); #ifdef BDB_BULK_SCAN delete[] bulk_buffer; #endif } int main(int argc, char * argv[]) { STXXL_MSG("stxxl::map Real Node block size: " << REAL_NODE_BLOCK_SIZE << " bytes"); STXXL_MSG("stxxl::map Real Leaf block size: " << REAL_LEAF_BLOCK_SIZE << " bytes"); STXXL_MSG("stxxl::map Node max elements : " << REAL_NODE_MELEMENTS); STXXL_MSG("stxxl::map Leaf max elements : " << REAL_LEAF_MELEMENTS); #ifdef STXXL_DIRECT_IO_OFF STXXL_MSG("STXXL_DIRECT_IO_OFF is defined"); #else STXXL_MSG("STXXL_DIRECT_IO_OFF is NOT defined"); #endif if (argc < 3) { STXXL_MSG("Usage: " << argv[0] << " version #ops"); STXXL_MSG("\t version = 1: test stxxl map"); STXXL_MSG("\t version = 2: test Berkeley DB btree"); STXXL_MSG("\t version = 3: big test stxxl map"); STXXL_MSG("\t version = 4: big test Berkeley DB btree"); STXXL_MSG("\t version = 5: big test TPIE btree"); return -1; } init(); int version = atoi(argv[1]); stxxl::int64 ops = stxxl::atoint64(argv[2]); STXXL_MSG("Running version : " << version); STXXL_MSG("Operations to perform: " << ops); STXXL_MSG("Btree cache size : " << TOTAL_CACHE_SIZE << " bytes"); STXXL_MSG("Leaf block size : " << LEAF_BLOCK_SIZE << " bytes"); switch (version) { case 1: run_stxxl_map(ops); break; case 2: run_bdb_btree(ops); break; case 3: run_stxxl_map_big(ops, 100000); break; case 4: run_bdb_btree_big(ops, 100000); break; case 5: run_tpie_btree_big(ops, 100000); break; default: STXXL_MSG("Unsupported version " << version); } } stxxl-1.3.1/containers/test_migr_stack.cpp0000644000175000017500000000375611026753412020561 0ustar andreasandreas/*************************************************************************** * containers/test_migr_stack.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2003 Roman Dementiev * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ //! \example containers/test_migr_stack.cpp //! This is an example of how to use \c stxxl::STACK_GENERATOR class //! to generate an \b migrating stack with critical size \c critical_size , //! external implementation \c normal_stack , \b four blocks per page, //! block size \b 4096 bytes, and internal implementation //! \c std::stack #include int main() { const unsigned critical_size = 8 * 4096; typedef stxxl::STACK_GENERATOR, critical_size>::result migrating_stack_type; STXXL_MSG("Starting test."); migrating_stack_type my_stack; int test_size = 1 * 1024 * 1024 / sizeof(int), i; STXXL_MSG("Filling stack."); for (i = 0; i < test_size; i++) { my_stack.push(i); assert(my_stack.top() == i); assert(my_stack.size() == i + 1); assert((my_stack.size() >= critical_size) == my_stack.external()); } STXXL_MSG("Testing swap."); // test swap migrating_stack_type my_stack2; std::swap(my_stack2, my_stack); std::swap(my_stack2, my_stack); STXXL_MSG("Removing elements from " << (my_stack.external() ? "external" : "internal") << " stack"); for (i = test_size - 1; i >= 0; i--) { assert(my_stack.top() == i); assert(my_stack.size() == i + 1); my_stack.pop(); assert(my_stack.size() == i); assert(my_stack.external() == (test_size >= int(critical_size))); } STXXL_MSG("Test passed."); return 0; } stxxl-1.3.1/containers/test_ext_merger2.cpp0000644000175000017500000001264611535151017020655 0ustar andreasandreas/*************************************************************************** * containers/test_ext_merger2.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright © 2008, 2009 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #include #include #include typedef int my_type; typedef stxxl::typed_block<4096, my_type> block_type; struct dummy_merger { int current, delta; dummy_merger() : current(0), delta(1) { } void operator () (int current_, int delta_) { current = current_; delta = delta_; } template void multi_merge(OutputIterator b, OutputIterator e) { while (b != e) { *b = current; ++b; current += delta; } } }; struct my_cmp : public std::greater { my_type min_value() const { return (std::numeric_limits::max)(); } }; my_type * make_sequence(dummy_merger & dummy, int l) { my_type * seq = new my_type[l + 1]; // + sentinel dummy.multi_merge(seq, seq + l); seq[l] = my_cmp().min_value(); // sentinel return seq; } int main() { stxxl::config::get_instance(); const int B = block_type::size; dummy_merger dummy; if (1) { const unsigned volume = 3 * 1024 * 1024; // in KiB const unsigned mem_for_queue = 256 * 1024 * 1024; typedef stxxl::PRIORITY_QUEUE_GENERATOR::result pq_type; pq_type pq(mem_for_queue, mem_for_queue); pq.push(42); assert(pq.top() == 42); pq.pop(); pq.push(2); pq.push(0); pq.push(3); pq.push(1); my_type x0, x1, x2, x3; x0 = pq.top(); pq.pop(); x1 = pq.top(); pq.pop(); x2 = pq.top(); pq.pop(); x3 = pq.top(); pq.pop(); STXXL_MSG("Order: " << x0 << " " << x1 << " " << x2 << " " << x3); assert(pq.empty()); } if (1) { // ext_merger test stxxl::read_write_pool pool(1, 2); stxxl::priority_queue_local::ext_merger merger(&pool); dummy(1, 0); merger.insert_segment(dummy, B * 2); dummy(2, 0); merger.insert_segment(dummy, B * 2); dummy(B, 1); merger.insert_segment(dummy, B * 4); dummy(B, 2); merger.insert_segment(dummy, B * 4); dummy(B, 4); merger.insert_segment(dummy, B * 4); std::vector output(B * 3); // zero length merge merger.multi_merge(output.begin(), output.begin()); merger.multi_merge(output.begin(), output.begin()); merger.multi_merge(output.begin(), output.begin()); while (merger.size() > 0) { int l = std::min(merger.size(), output.size()); merger.multi_merge(output.begin(), output.begin() + l); STXXL_MSG("merged " << l << " elements: (" << *output.begin() << ", ..., " << *(output.begin() + l - 1) << ")"); } // zero length merge on empty data structure merger.multi_merge(output.begin(), output.begin()); merger.multi_merge(output.begin(), output.begin()); merger.multi_merge(output.begin(), output.begin()); } // ext_merger test if (1) { // loser_tree test stxxl::priority_queue_local::loser_tree loser; dummy(1, 0); my_type * seq0 = make_sequence(dummy, 2 * B); dummy(2, 0); my_type * seq1 = make_sequence(dummy, 2 * B); dummy(B, 1); my_type * seq2 = make_sequence(dummy, 4 * B); dummy(B, 2); my_type * seq3 = make_sequence(dummy, 4 * B); dummy(2 * B, 1); my_type * seq4 = make_sequence(dummy, 4 * B); dummy(B, 4); my_type * seq5 = make_sequence(dummy, 4 * B); dummy(B, 8); my_type * seq6 = make_sequence(dummy, 4 * B); dummy(2 * B, 2); my_type * seq7 = make_sequence(dummy, 4 * B); loser.init(); loser.insert_segment(seq0, 2 * B); loser.insert_segment(seq1, 2 * B); loser.insert_segment(seq2, 4 * B); loser.insert_segment(seq3, 4 * B); loser.insert_segment(seq4, 4 * B); if (0) { loser.insert_segment(seq5, 4 * B); loser.insert_segment(seq6, 4 * B); loser.insert_segment(seq7, 4 * B); } else { delete[] seq5; delete[] seq6; delete[] seq7; } my_type * out = new my_type[2 * B]; // zero length merge loser.multi_merge(out, out); loser.multi_merge(out, out); loser.multi_merge(out, out); while (loser.size() > 0) { int l = std::min(loser.size(), B + B / 2 + 1); loser.multi_merge(out, out + l); STXXL_MSG("merged " << l << " elements: (" << out[0] << ", ..., " << out[l - 1] << ")"); } // zero length merge on empty data structure loser.multi_merge(out, out); loser.multi_merge(out, out); loser.multi_merge(out, out); delete[] out; } // loser_tree test } // vim: et:ts=4:sw=4 stxxl-1.3.1/containers/run_bdb_test0000755000175000017500000000056110622615152017261 0ustar andreasandreas#!/bin/bash export LD_LIBRARY_PATH=/usr/local/BerkeleyDB.4.4/lib/ SUF=4 #LIMIT=1073741824 #LIMIT=4194304 LIMIT=16777216 for ((n=1024; n <= LIMIT ; n=n*2)) do echo "Running test with $n items" ./berkeley_db_benchmark.bin 1 $n >> map_${n}.log.$SUF 2>> map_${n}.log.$SUF ./berkeley_db_benchmark.bin 2 $n >> bdb_${n}.log.$SUF 2>> bdb_${n}.log.$SUF done stxxl-1.3.1/containers/pq_benchmark.cpp0000644000175000017500000001477011535151017020025 0ustar andreasandreas/*************************************************************************** * containers/pq_benchmark.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2006 Roman Dementiev * Copyright (C) 2009 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ //! \example containers/pq_benchmark.cpp //! This is a benchmark mentioned in the paper //! R. Dementiev, L. Kettner, P. Sanders "STXXL: standard template library for XXL data sets" //! Software: Practice and Experience //! Volume 38, Issue 6, Pages 589-637, May 2008 //! DOI: 10.1002/spe.844 #include #include #include #include #define TOTAL_PQ_MEM_SIZE (768 * 1024 * 1024) #define PQ_MEM_SIZE (512 * 1024 * 1024) #define PREFETCH_POOL_SIZE ((TOTAL_PQ_MEM_SIZE - PQ_MEM_SIZE) / 2) #define WRITE_POOL_SIZE (PREFETCH_POOL_SIZE) #define MAX_ELEMENTS (2000 * 1024 * 1024) struct my_record { int key; int data; my_record() : key(0), data(0) { } my_record(int k, int d) : key(k), data(d) { } }; std::ostream & operator << (std::ostream & o, const my_record & obj) { o << obj.key << " " << obj.data; return o; } bool operator == (const my_record & a, const my_record & b) { return a.key == b.key; } bool operator != (const my_record & a, const my_record & b) { return a.key != b.key; } bool operator < (const my_record & a, const my_record & b) { return a.key < b.key; } bool operator > (const my_record & a, const my_record & b) { return a.key > b.key; } struct comp_type : std::binary_function { bool operator () (const my_record & a, const my_record & b) const { return a > b; } static my_record min_value() { return my_record((std::numeric_limits::max)(), 0); } }; typedef stxxl::PRIORITY_QUEUE_GENERATOR::result pq_type; typedef pq_type::block_type block_type; #define BLOCK_SIZE block_type::raw_size #if 1 unsigned ran32State = 0xdeadbeef; inline int myrand() { return ((int)((ran32State = 1664525 * ran32State + 1013904223) >> 1)) - 1; } #else // a longer pseudo random sequence long long unsigned ran32State = 0xdeadbeef; inline long long unsigned myrand() { return (ran32State = (ran32State * 0x5DEECE66DULL + 0xBULL) & 0xFFFFFFFFFFFFULL); } #endif void run_stxxl_insert_all_delete_all(stxxl::uint64 ops) { pq_type PQ(PREFETCH_POOL_SIZE, WRITE_POOL_SIZE); stxxl::uint64 i; my_record cur; stxxl::stats_data stats_begin(*stxxl::stats::get_instance()); stxxl::timer Timer; Timer.start(); for (i = 0; i < ops; ++i) { cur.key = myrand(); PQ.push(cur); } Timer.stop(); STXXL_MSG("Records in PQ: " << PQ.size()); if (i != PQ.size()) { STXXL_MSG("Size does not match"); abort(); } STXXL_MSG("Insertions elapsed time: " << (Timer.mseconds() / 1000.) << " seconds : " << (double(ops) / (Timer.mseconds() / 1000.)) << " key/data pairs per sec"); std::cout << stxxl::stats_data(*stxxl::stats::get_instance()) - stats_begin; //////////////////////////////////////////////// stats_begin = *stxxl::stats::get_instance(); Timer.reset(); Timer.start(); for (i = 0; i < ops; ++i) { PQ.pop(); } Timer.stop(); STXXL_MSG("Records in PQ: " << PQ.size()); if (!PQ.empty()) { STXXL_MSG("PQ must be empty"); abort(); } STXXL_MSG("Deletions elapsed time: " << (Timer.mseconds() / 1000.) << " seconds : " << (double(ops) / (Timer.mseconds() / 1000.)) << " key/data pairs per sec"); std::cout << stxxl::stats_data(*stxxl::stats::get_instance()) - stats_begin; } void run_stxxl_intermixed(stxxl::uint64 ops) { pq_type PQ(PREFETCH_POOL_SIZE, WRITE_POOL_SIZE); stxxl::uint64 i; my_record cur; stxxl::stats_data stats_begin(*stxxl::stats::get_instance()); stxxl::timer Timer; Timer.start(); for (i = 0; i < ops; ++i) { cur.key = myrand(); PQ.push(cur); } Timer.stop(); STXXL_MSG("Records in PQ: " << PQ.size()); if (i != PQ.size()) { STXXL_MSG("Size does not match"); abort(); } STXXL_MSG("Insertions elapsed time: " << (Timer.mseconds() / 1000.) << " seconds : " << (double(ops) / (Timer.mseconds() / 1000.)) << " key/data pairs per sec"); std::cout << stxxl::stats_data(*stxxl::stats::get_instance()) - stats_begin; //////////////////////////////////////////////// stats_begin = *stxxl::stats::get_instance(); Timer.reset(); Timer.start(); for (i = 0; i < ops; ++i) { int o = myrand() % 3; if (o == 0) { cur.key = myrand(); PQ.push(cur); } else { assert(!PQ.empty()); PQ.pop(); } } Timer.stop(); STXXL_MSG("Records in PQ: " << PQ.size()); STXXL_MSG("Deletions/Insertion elapsed time: " << (Timer.mseconds() / 1000.) << " seconds : " << (double(ops) / (Timer.mseconds() / 1000.)) << " key/data pairs per sec"); std::cout << stxxl::stats_data(*stxxl::stats::get_instance()) - stats_begin; } int main(int argc, char * argv[]) { STXXL_MSG("stxxl::pq lock size: " << BLOCK_SIZE << " bytes"); #ifdef STXXL_DIRECT_IO_OFF STXXL_MSG("STXXL_DIRECT_IO_OFF is defined"); #else STXXL_MSG("STXXL_DIRECT_IO_OFF is NOT defined"); #endif if (argc < 3) { STXXL_MSG("Usage: " << argv[0] << " version #ops"); STXXL_MSG("\t version = 1: insert-all-delete-all stxxl pq"); STXXL_MSG("\t version = 2: intermixed insert/delete stxxl pq"); return -1; } int version = atoi(argv[1]); stxxl::int64 ops = stxxl::atoint64(argv[2]); STXXL_MSG("Running version : " << version); STXXL_MSG("Operations to perform: " << ops); switch (version) { case 1: run_stxxl_insert_all_delete_all(ops); break; case 2: run_stxxl_intermixed(ops); break; default: STXXL_MSG("Unsupported version " << version); } } stxxl-1.3.1/containers/Makefile0000644000175000017500000001355611500030337016321 0ustar andreasandreasinclude Makefile.common include ../make.settings tests: $(TESTS) $(TESTS_MAP) cd btree $(MAKE) tests cd .. #tests: $(TESTS_NON_MSVC) NDEBUG = #-DNDEBUG DEPENDENCIES = $(COMMON_FILES) $(IO_LAYER_FILES) $(MNG_LAYER_FILES) $(CONTAINER_FILES) stack_benchmark: stack_benchmark.$(EXEEXT) stack_benchmark.$(EXEEXT): stack_benchmark.cpp $(DEPENDENCIES) $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c stack_benchmark.cpp $(NDEBUG) $(LINKER) stack_benchmark.$(OBJEXT) $(OUT)stack_benchmark.$(EXEEXT) $(STXXL_LINKER_OPTIONS) test_iterators: test_iterators.$(EXEEXT) test_iterators.$(EXEEXT): test_iterators.cpp $(DEPENDENCIES) $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c test_iterators.cpp $(LINKER) test_iterators.$(OBJEXT) $(OUT)test_iterators.$(EXEEXT) $(STXXL_LINKER_OPTIONS) test_deque: test_deque.$(EXEEXT) test_deque.$(EXEEXT): test_deque.cpp $(DEPENDENCIES) $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c test_deque.cpp $(LINKER) test_deque.$(OBJEXT) $(OUT)test_deque.$(EXEEXT) $(STXXL_LINKER_OPTIONS) pq_benchmark: pq_benchmark.$(EXEEXT) pq_benchmark.$(EXEEXT): pq_benchmark.cpp $(DEPENDENCIES) $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c pq_benchmark.cpp $(NDEBUG) $(LINKER) pq_benchmark.$(OBJEXT) $(OUT)pq_benchmark.$(EXEEXT) $(STXXL_LINKER_OPTIONS) write_vector: write_vector.$(EXEEXT) write_vector.$(EXEEXT): write_vector.cpp $(DEPENDENCIES) $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c write_vector.cpp $(LINKER) write_vector.$(OBJEXT) $(OUT)write_vector.$(EXEEXT) $(STXXL_LINKER_OPTIONS) write_vector2: write_vector2.$(EXEEXT) write_vector2.$(EXEEXT): write_vector2.cpp $(DEPENDENCIES) $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c write_vector2.cpp $(LINKER) write_vector2.$(OBJEXT) $(OUT)write_vector2.$(EXEEXT) $(STXXL_LINKER_OPTIONS) test_queue: test_queue.$(EXEEXT) test_queue.$(EXEEXT): test_queue.cpp $(DEPENDENCIES) $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c test_queue.cpp $(LINKER) test_queue.$(OBJEXT) $(OUT)test_queue.$(EXEEXT) $(STXXL_LINKER_OPTIONS) test_map: test_map.$(EXEEXT) test_map.$(EXEEXT): test_map.cpp $(DEPENDENCIES) $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c test_map.cpp $(LINKER) test_map.$(OBJEXT) $(OUT)test_map.$(EXEEXT) $(STXXL_LINKER_OPTIONS) test_map_random: test_map_random.$(EXEEXT) test_map_random.$(EXEEXT): test_map_random.cpp map_test_handlers.h $(DEPENDENCIES) $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c test_map_random.cpp $(LINKER) test_map_random.$(OBJEXT) $(OUT)test_map_random.$(EXEEXT) $(STXXL_LINKER_OPTIONS) copy_file: copy_file.$(EXEEXT) copy_file.$(EXEEXT): copy_file.cpp $(DEPENDENCIES) $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c copy_file.cpp $(LINKER) copy_file.$(OBJEXT) $(OUT)copy_file.$(EXEEXT) $(STXXL_LINKER_OPTIONS) test_vector: test_vector.$(EXEEXT) test_vector.$(EXEEXT): test_vector.cpp $(DEPENDENCIES) $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c test_vector.cpp $(LINKER) test_vector.$(OBJEXT) $(OUT)test_vector.$(EXEEXT) $(STXXL_LINKER_OPTIONS) test_vector_export: test_vector_export.$(EXEEXT) test_vector_export.$(EXEEXT): test_vector_export.cpp $(DEPENDENCIES) $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c test_vector_export.cpp $(LINKER) test_vector_export.$(OBJEXT) $(OUT)test_vector_export.$(EXEEXT) $(STXXL_LINKER_OPTIONS) test_stack: test_stack.$(EXEEXT) test_stack.$(EXEEXT): test_stack.cpp $(DEPENDENCIES) $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c test_stack.cpp $(LINKER) test_stack.$(OBJEXT) $(OUT)test_stack.$(EXEEXT) $(STXXL_LINKER_OPTIONS) test_migr_stack: test_migr_stack.$(EXEEXT) test_migr_stack.$(EXEEXT): test_migr_stack.cpp $(DEPENDENCIES) $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c test_migr_stack.cpp $(LINKER) test_migr_stack.$(OBJEXT) $(OUT)test_migr_stack.$(EXEEXT) $(STXXL_LINKER_OPTIONS) test_many_stacks: test_many_stacks.$(EXEEXT) test_many_stacks.$(EXEEXT): test_many_stacks.cpp $(DEPENDENCIES) $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c test_many_stacks.cpp -DSTXXL_VERBOSE_LEVEL=1 $(LINKER) test_many_stacks.$(OBJEXT) $(OUT)test_many_stacks.$(EXEEXT) $(STXXL_LINKER_OPTIONS) test_pqueue: test_pqueue.$(EXEEXT) test_pqueue.$(EXEEXT): test_pqueue.cpp $(DEPENDENCIES) $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c test_pqueue.cpp $(LINKER) test_pqueue.$(OBJEXT) $(OUT)test_pqueue.$(EXEEXT) $(STXXL_LINKER_OPTIONS) test_ext_merger: test_ext_merger.$(EXEEXT) test_ext_merger.$(EXEEXT): test_ext_merger.cpp $(DEPENDENCIES) $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c test_ext_merger.cpp -DSTXXL_VERBOSE_LEVEL=1 $(LINKER) test_ext_merger.$(OBJEXT) $(OUT)test_ext_merger.$(EXEEXT) $(STXXL_LINKER_OPTIONS) test_ext_merger2: test_ext_merger2.$(EXEEXT) test_ext_merger2.$(EXEEXT): test_ext_merger2.cpp $(DEPENDENCIES) $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c test_ext_merger2.cpp -DSTXXL_VERBOSE_LEVEL=1 $(LINKER) test_ext_merger2.$(OBJEXT) $(OUT)test_ext_merger2.$(EXEEXT) $(STXXL_LINKER_OPTIONS) bench_pqueue: bench_pqueue.$(EXEEXT) bench_pqueue.$(EXEEXT): bench_pqueue.cpp $(DEPENDENCIES) $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c bench_pqueue.cpp -DSTXXL_VERBOSE_LEVEL=0 $(LINKER) bench_pqueue.$(OBJEXT) $(OUT)bench_pqueue.$(EXEEXT) $(STXXL_LINKER_OPTIONS) monotonic_pq: monotonic_pq.$(EXEEXT) monotonic_pq.$(EXEEXT): monotonic_pq.cpp $(DEPENDENCIES) $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c monotonic_pq.cpp $(LINKER) monotonic_pq.$(OBJEXT) $(OUT)monotonic_pq.$(EXEEXT) $(STXXL_LINKER_OPTIONS) benchmark_naive_matrix: benchmark_naive_matrix.$(EXEEXT) benchmark_naive_matrix.$(EXEEXT): benchmark_naive_matrix.cpp $(DEPENDENCIES) $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c benchmark_naive_matrix.cpp -DSTXXL_VERBOSE_LEVEL=0 $(LINKER) benchmark_naive_matrix.$(OBJEXT) $(OUT)benchmark_naive_matrix.$(EXEEXT) $(STXXL_LINKER_OPTIONS) test_vector_sizes: test_vector_sizes.$(EXEEXT) test_vector_sizes.$(EXEEXT): test_vector_sizes.cpp $(DEPENDENCIES) $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c test_vector_sizes.cpp $(LINKER) test_vector_sizes.$(OBJEXT) $(OUT)test_vector_sizes.$(EXEEXT) $(STXXL_LINKER_OPTIONS) clean: $(RM) $(CLEAN_TARGETS) cd btree $(MAKE) clean cd .. stxxl-1.3.1/containers/test_deque.cpp0000644000175000017500000000652311535151017017532 0ustar andreasandreas/*************************************************************************** * containers/test_deque.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2006 Roman Dementiev * Copyright (C) 2009 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #include #include int main(int argc, char * argv[]) { if (argc != 2) { STXXL_MSG("Usage: " << argv[0] << " #ops"); return -1; } stxxl::deque Deque; stxxl::deque::const_iterator b = Deque.begin(); stxxl::deque::const_iterator e = Deque.end(); assert(b == e); Deque.push_front(1); Deque.push_front(2); Deque.push_front(3); b = Deque.begin(); assert(b != e); Deque.push_back(5); std::copy(Deque.begin(), Deque.end(), std::ostream_iterator(std::cout, " ")); stxxl::random_number32 rand; stxxl::deque XXLDeque; std::deque STDDeque; stxxl::int64 ops = stxxl::atoint64(argv[1]); for (stxxl::int64 i = 0; i < ops; ++i) { unsigned curOP = rand() % 6; unsigned value = rand(); switch (curOP) { case 0: case 1: XXLDeque.push_front(value); STDDeque.push_front(value); break; case 2: XXLDeque.push_back(value); STDDeque.push_back(value); break; case 3: if (!XXLDeque.empty()) { XXLDeque.pop_front(); STDDeque.pop_front(); } break; case 4: if (!XXLDeque.empty()) { XXLDeque.pop_back(); STDDeque.pop_back(); } break; case 5: if (XXLDeque.size() > 0) { stxxl::deque::iterator XXLI = XXLDeque.begin() + (value % XXLDeque.size()); std::deque::iterator STDI = STDDeque.begin() + (value % STDDeque.size()); *XXLI = value; *STDI = value; unsigned value1 = rand(); if (XXLI - XXLDeque.begin() == 0) break; XXLI = XXLI - (value1 % (XXLI - XXLDeque.begin())); STDI = STDI - (value1 % (STDI - STDDeque.begin())); *XXLI = value1; *STDI = value1; } break; } assert(XXLDeque.empty() == STDDeque.empty()); assert(XXLDeque.size() == STDDeque.size()); assert(XXLDeque.end() - XXLDeque.begin() == STDDeque.end() - STDDeque.begin()); //assert(std::equal(XXLDeque.begin(),XXLDeque.end(),STDDeque.begin() _STXXL_FORCE_SEQUENTIAL)); if (XXLDeque.size() > 0) { assert(XXLDeque.back() == STDDeque.back()); assert(XXLDeque.front() == STDDeque.front()); } if (!(i % 100000)) { assert(std::equal(XXLDeque.begin(), XXLDeque.end(), STDDeque.begin() _STXXL_FORCE_SEQUENTIAL)); STXXL_MSG("Operations done: " << i << " size: " << STDDeque.size()); } } return 0; } stxxl-1.3.1/containers/test_vector_export.cpp0000644000175000017500000000323411157703330021327 0ustar andreasandreas/*************************************************************************** * containers/test_vector_export.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2008 Johannes Singler * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ //! \example containers/test_vector_export.cpp //! This is an example of use of \c stxxl::vector::export_files #include #include #include #include typedef stxxl::int64 int64; int main() { try { // use non-randomized striping to avoid side effects on random generator typedef stxxl::VECTOR_GENERATOR::result vector_type; vector_type v(int64(64 * 1024 * 1024) / sizeof(int64)); stxxl::random_number32 rnd; int offset = rnd(); STXXL_MSG("write " << v.size() << " elements"); stxxl::ran32State = 0xdeadbeef; vector_type::size_type i; // fill the vector with increasing sequence of integer numbers for (i = 0; i < v.size(); ++i) { v[i] = i + offset; assert(v[i] == int64(i + offset)); } v.flush(); STXXL_MSG("export files"); v.export_files("exported_"); } catch (const std::exception & ex) { STXXL_MSG("Caught exception: " << ex.what()); } catch (...) { STXXL_MSG("Caught unknown exception."); } return 0; } stxxl-1.3.1/containers/leda_sm_stack_benchmark.cpp0000644000175000017500000000770111202521435022166 0ustar andreasandreas/*************************************************************************** * containers/leda_sm_stack_benchmark.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2006 Roman Dementiev * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ //! \example containers/leda_sm_stack_benchmark.cpp //! This is a benchmark mentioned in the paper //! R. Dementiev, L. Kettner, P. Sanders "STXXL: standard template library for XXL data sets" //! Software: Practice and Experience //! Volume 38, Issue 6, Pages 589-637, May 2008 //! DOI: 10.1002/spe.844 #include #include #include #include #include #include #include #include #include #define DEBUG 0 #define DD 500 #include #include #define STXXL_MSG(x) \ { std::cout << "[STXXL-MSG] " << x << std::endl << std::flush; \ } #define MEM_2_RESERVE (768 * 1024 * 1024) #define BLOCK_SIZE1 (EXT_BLK_SZ * 4) #define BLOCK_SIZE2 (DISK_BLOCK_SIZE * 4) #ifndef DISKS #define DISKS 1 #endif template struct my_record_ { char data[RECORD_SIZE]; my_record_() { } }; template void run_stack(stxxl::int64 volume) { typedef ext_stack stack_type; STXXL_MSG("Record size: " << sizeof(my_record) << " bytes"); stack_type Stack; stxxl::int64 ops = volume / sizeof(my_record); stxxl::int64 i; my_record cur; stxxl::timer Timer; Timer.start(); for (i = 0; i < ops; ++i) { Stack.push(cur); } Timer.stop(); STXXL_MSG("Records in Stack: " << Stack.size()); if (i != Stack.size()) { STXXL_MSG("Size does not match"); abort(); } STXXL_MSG("Insertions elapsed time: " << (Timer.mseconds() / 1000.) << " seconds : " << (double(volume) / (1024. * 1024. * Timer.mseconds() / 1000.)) << " MiB/s"); ext_mem_mgr.print_statistics(); ext_mem_mgr.reset_statistics(); //////////////////////////////////////////////// Timer.reset(); Timer.start(); for (i = 0; i < ops; ++i) { Stack.pop(); } Timer.stop(); STXXL_MSG("Records in Stack: " << Stack.size()); if (!Stack.empty()) { STXXL_MSG("Stack must be empty"); abort(); } STXXL_MSG("Deletions elapsed time: " << (Timer.mseconds() / 1000.) << " seconds : " << (double(volume) / (1024. * 1024. * Timer.mseconds() / 1000.)) << " MiB/s"); ext_mem_mgr.print_statistics(); } int main(int argc, char * argv[]) { STXXL_MSG("block size 1: " << BLOCK_SIZE1 << " bytes"); STXXL_MSG("block size 2: " << BLOCK_SIZE2 << " bytes"); if (argc < 3) { STXXL_MSG("Usage: " << argv[0] << " version #volume"); STXXL_MSG("\t version = 1: LEDA-SM stack with 4 byte records"); STXXL_MSG("\t version = 2: LEDA-SM stack with 32 byte records"); return -1; } int version = atoi(argv[1]); stxxl::int64 volume = atoll(argv[2]); STXXL_MSG("Allocating array with size " << MEM_2_RESERVE << " bytes to prevent file buffering."); int * array = new int[MEM_2_RESERVE / sizeof(int)]; std::fill(array, array + (MEM_2_RESERVE / sizeof(int)), 0); STXXL_MSG("Running version: " << version); STXXL_MSG("Data volume : " << volume << " bytes"); switch (version) { case 1: run_stack >(volume); break; case 2: run_stack >(volume); break; default: STXXL_MSG("Unsupported version " << version); } delete[] array; } stxxl-1.3.1/containers/bench_pqueue.cpp0000644000175000017500000000677611535151017020045 0ustar andreasandreas/*************************************************************************** * containers/bench_pqueue.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2003 Roman Dementiev * Copyright (C) 2009 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #include #include #include #define RECORD_SIZE 20 struct my_type { //typedef stxxl::int64 key_type; typedef int key_type; key_type key; char data[RECORD_SIZE - sizeof(key_type)]; my_type() { } explicit my_type(key_type k) : key(k) { #ifdef STXXL_VALGRIND_AVOID_UNINITIALIZED_WRITE_ERRORS memset(data, 0, sizeof(data)); #endif } }; std::ostream & operator << (std::ostream & o, const my_type & obj) { o << obj.key; return o; } struct my_cmp : std::binary_function // greater { bool operator () (const my_type & a, const my_type & b) const { return a.key > b.key; } my_type min_value() const { return my_type((std::numeric_limits::max)()); } }; int main() { /* unsigned BufferSize1_ = 32, // equalize procedure call overheads etc. unsigned N_ = 512, // bandwidth unsigned IntKMAX_ = 64, // maximal arity for internal mergers unsigned IntLevels_ = 4, unsigned BlockSize_ = (2*1024*1024), unsigned ExtKMAX_ = 64, // maximal arity for external mergers unsigned ExtLevels_ = 2, */ // typedef priority_queue > pq_type; const unsigned volume = 3 * 1024 * 1024; // in KiB const unsigned mem_for_queue = 256 * 1024 * 1024; const unsigned mem_for_pools = 512 * 1024 * 1024; typedef stxxl::PRIORITY_QUEUE_GENERATOR gen; typedef gen::result pq_type; typedef pq_type::block_type block_type; STXXL_MSG("Block size: " << block_type::raw_size); STXXL_MSG("AI: " << gen::AI); STXXL_MSG("X : " << gen::X); STXXL_MSG("N : " << gen::N); STXXL_MSG("AE: " << gen::AE); stxxl::timer Timer; Timer.start(); pq_type p(mem_for_pools / 2, mem_for_pools / 2); stxxl::int64 nelements = stxxl::int64(volume / sizeof(my_type)) * 1024, i; STXXL_MSG("Internal memory consumption of the priority queue: " << p.mem_cons() << " B"); STXXL_MSG("Max elements: " << nelements); for (i = 0; i < nelements; i++) { if ((i % (1024 * 1024)) == 0) STXXL_MSG("Inserting element " << i); p.push(my_type(nelements - i)); } Timer.stop(); STXXL_MSG("Time spent for filling: " << Timer.seconds() << " s"); STXXL_MSG("Internal memory consumption of the priority queue: " << p.mem_cons() << " B"); Timer.reset(); Timer.start(); for (i = 0; i < (nelements); ++i) { assert(!p.empty()); //STXXL_MSG( p.top() ); assert(p.top().key == i + 1); p.pop(); if ((i % (1024 * 1024)) == 0) STXXL_MSG("Element " << i << " popped"); } Timer.stop(); STXXL_MSG("Time spent for removing elements: " << Timer.seconds() << " s"); STXXL_MSG("Internal memory consumption of the priority queue: " << p.mem_cons() << " B"); } stxxl-1.3.1/containers/GNUmakefile0000644000175000017500000001375711515264656016761 0ustar andreasandreasTOPDIR ?= .. include Makefile.common -include $(TOPDIR)/make.settings.local ENABLE_BTREE ?= yes ENABLE_BDB ?= no ENABLE_LEDASM ?= no ENABLE_TPIE ?= no TESTS-yes += $(TESTS_NON_MSVC) TESTS-$(ENABLE_BTREE) += $(TESTS_MAP) TESTS-$(ENABLE_BTREE) += $(TESTS_BTREE:%=btree/%) TESTS-$(ENABLE_BDB)$(ENABLE_TPIE) += $(TESTS_BDB) ifneq ($(strip $(USE_BOOST)),yes) TESTS-$(ENABLE_LEDASM) += $(TESTS_LEDASM) endif TESTS-$(ENABLE_TPIE) += $(TESTS_TPIE) include $(TOPDIR)/Makefile.subdir.gnu CPPFLAGS_BDB ?= LIBS_BDB ?= -ldb_cxx TPIE_ROOT ?= /usr/local/tpie TPIE_ROOT ?= $(HOME)/projects/tpie_091905 TPIE_ROOT ?= $(HOME)/work/lib/tpie TPIE_ROOT ?= $(HOME)/work/lib/$(UNAME_M)/tpie CPPFLAGS_TPIE ?= -I$(TPIE_ROOT)/include -DHAVE_CONFIG_H LIBS_TPIE ?= -L$(TPIE_ROOT)/lib -ltpie LEDA_COMPILER ?= g++-2.95 LEDA_FLAGS ?= -D_LINUX $(filter-out -openmp -fopenmp -D__MCSTL__ -include stxxl/bits/defines.h,$(STXXL_COMPILER_OPTIONS)) -Wno-error LEDA_ROOT ?= /usr/local/LEDA LEDA_SM_ROOT ?= /usr/local/LEDA-SM LEDA_COMPILER ?= /usr/local/bin/g++-2.95.3 LEDA_FLAGS ?= -fpic -D_LINUX -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -O3 LEDA_ROOT ?= /software/LEDA/4.2.1 LEDA_SM_ROOT ?= /home/dementiev/projects/LEDA-SM-1.3 LEDA_SM_CPP_FLAGS ?= -I$(LEDA_ROOT)/incl -I$(LEDA_SM_ROOT)/incl $(LEDA_FLAGS) LEDA_SM_LDFLAGS ?= -L$(LEDA_ROOT) -Wl,-R$(LEDA_ROOT) -L$(LEDA_SM_ROOT) #-L/usr/X11R6/lib LEDA_SM_LDFLAGS ?= -L$(LEDA_ROOT) -L$(LEDA_SM_ROOT) -L/usr/X11R6/lib -Xlinker -rpath -Xlinker $(LEDA_ROOT) #-Xlinker -rpath -Xlinker $(LEDA_SM_ROOT) LEDA_SM_LDLIBS ?= -lLEDA-SM -lL LEDA_SM_LDLIBS ?= -lW -lP -lG -lL -lX11 -lm -lLEDA-SM #stack_benchmark.$o: CPPFLAGS += -DNDEBUG #pq_benchmark.$o: CPPFLAGS += -DNDEBUG test_many_stacks.$o: CPPFLAGS += -DSTXXL_VERBOSE_LEVEL=1 test_ext_merger.$o: CPPFLAGS += -DSTXXL_VERBOSE_LEVEL=1 test_ext_merger2.$o: CPPFLAGS += -DSTXXL_VERBOSE_LEVEL=1 $(TESTS_BDB:=.$(bin)): CPPFLAGS += $(CPPFLAGS_TPIE) $(CPPFLAGS_BDB) $(TESTS_BDB:=.$(bin)): STXXL_LINKER_OPTIONS += $(LIBS_TPIE) $(LIBS_BDB) $(TESTS_TPIE:=.$(bin)): CPPFLAGS += $(CPPFLAGS_TPIE) $(TESTS_TPIE:=.$(bin)): STXXL_LINKER_OPTIONS += $(LIBS_TPIE) leda_sm_pq_benchmark.$(bin): leda_sm_pq_benchmark.cpp GNUmakefile $(LEDA_COMPILER) $(LEDA_SM_CPP_FLAGS) -o leda_sm_pq_benchmark.$(OBJEXT) -c leda_sm_pq_benchmark.cpp $(LEDA_COMPILER) -o leda_sm_pq_benchmark.$(EXEEXT) leda_sm_pq_benchmark.$(OBJEXT) $(LEDA_SM_LDFLAGS) $(LEDA_SM_LDLIBS) leda_sm_stack_benchmark.$(bin): leda_sm_stack_benchmark.cpp GNUmakefile $(LEDA_COMPILER) $(LEDA_SM_CPP_FLAGS) -o leda_sm_stack_benchmark.$(OBJEXT) -c leda_sm_stack_benchmark.cpp $(LEDA_COMPILER) -o leda_sm_stack_benchmark.$(EXEEXT) leda_sm_stack_benchmark.$(OBJEXT) $(LEDA_SM_LDFLAGS) $(LEDA_SM_LDLIBS) ifeq ($(strip $(USE_PMODE)),yes) # ICPC 12.0: internal error: backend signals (issue 613286) $(call reduce_optimization,3,0,test_pqueue,Version_12.0,any,any) $(call reduce_optimization,3,0,test_ext_merger2,Version_12.0,any,any) $(call reduce_optimization,3,0,bench_pqueue,Version_12.0,any,any) $(call reduce_optimization,3,0,monotonic_pq,Version_12.0,any,any) $(call reduce_optimization,3,0,pq_benchmark,Version_12.0,any,any) $(call reduce_optimization,3,0,btree/test_corr_insert_erase,Version_12.0,any,any) $(call reduce_optimization,3,0,btree/test_corr_insert_scan,Version_12.0,any,any) $(call reduce_optimization,3,0,berkeley_db_benchmark,Version_12.0,any,any) endif ifeq ($(strip $(USE_MCSTL)),yes) # PR33361: internal compiler error: in find_outermost_region_in_block, at tree-cfg.c:4803 # when using g++-4.2 -fopenmp -O3. Fixed in g++-4.3, wontfix in g++-4.2. ifneq ($(strip $(USE_BOOST)),yes) $(call reduce_optimization,3,2,berkeley_db_benchmark,gcc_version_4.2,32-bit,any) $(call reduce_optimization,3,2,test_map,gcc_version_4.2,64-bit,any) $(call reduce_optimization,3,1,test_map,gcc_version_4.2,32-bit,any) $(call reduce_optimization,3,0,test_map_random,gcc_version_4.2,64-bit,any) $(call reduce_optimization,3,0,test_map_random,gcc_version_4.2,32-bit,any) $(call reduce_optimization,3,0,btree/test_btree,gcc_version_4.2,64-bit,any) $(call reduce_optimization,3,0,btree/test_btree,gcc_version_4.2,32-bit,any) $(call reduce_optimization,3,0,btree/test_const_scan,gcc_version_4.2,64-bit,any) $(call reduce_optimization,3,0,btree/test_const_scan,gcc_version_4.2,32-bit,any) else $(call reduce_optimization,3,0,berkeley_db_benchmark,gcc_version_4.2,64-bit,any) $(call reduce_optimization,3,0,berkeley_db_benchmark,gcc_version_4.2,32-bit,any) endif # ICPC 12.0: internal error: backend signals (issue 613286) $(call reduce_optimization,3,0,test_pqueue,Version_12.0,any,any) $(call reduce_optimization,3,0,test_ext_merger,Version_12.0,any,any) $(call reduce_optimization,3,0,test_ext_merger2,Version_12.0,any,any) $(call reduce_optimization,3,0,bench_pqueue,Version_12.0,any,any) $(call reduce_optimization,3,0,monotonic_pq,Version_12.0,any,any) $(call reduce_optimization,3,0,pq_benchmark,Version_12.0,any,any) $(call reduce_optimization,3,0,test_map_random,Version_12.0,any,any) $(call reduce_optimization,3,0,btree/test_btree,Version_12.0,any,any) $(call reduce_optimization,3,0,btree/test_const_scan,Version_12.0,any,any) $(call reduce_optimization,3,0,btree/test_corr_insert_erase,Version_12.0,any,any) $(call reduce_optimization,3,0,btree/test_corr_insert_scan,Version_12.0,any,any) $(call reduce_optimization,3,0,berkeley_db_benchmark,Version_12.0,any,any) # ICPC 11.0: internal error: 0_1374 (issue 539748) $(call reduce_optimization,3,1,btree/test_btree,Version_11.0,any,any) $(call reduce_optimization,3,1,btree/test_const_scan,Version_11.0,any,any) $(call reduce_optimization,3,0,btree/test_corr_insert_erase,Version_11.0,any,any) $(call reduce_optimization,3,0,btree/test_corr_insert_scan,Version_11.0,any,any) # ICPC 10.0: internal error: backend signals (issue 466173) $(call reduce_optimization,3,1,btree/test_corr_insert_erase,Version_10.0,32-bit,any) $(call reduce_optimization,3,1,btree/test_corr_insert_scan,Version_10.0,32-bit,any) endif clean:: $(RM) btree/*.$o btree/*.$(o:.o=).d btree/*.dT -include btree/*.d stxxl-1.3.1/containers/copy_file.cpp0000644000175000017500000000346011031437521017334 0ustar andreasandreas/*************************************************************************** * containers/copy_file.cpp * * copies a file to another file * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2004-2006 Roman Dementiev * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #include #include typedef unsigned char my_type; using stxxl::syscall_file; using stxxl::file; int main(int argc, char * argv[]) { if (argc < 3) { std::cout << "Usage: " << argv[0] << " input_file output_file " << std::endl; return -1; } unlink(argv[2]); // delete output file syscall_file InputFile(argv[1], file::RDONLY); // Input file object syscall_file OutputFile(argv[2], file::RDWR | file::CREAT); // Output file object typedef stxxl::vector vector_type; std::cout << "Copying file " << argv[1] << " to " << argv[2] << std::endl; vector_type InputVector(&InputFile); // InputVector is mapped to InputFile vector_type OutputVector(&OutputFile); // OutputVector is mapped to OutputFile std::cout << "File " << argv[1] << " has size " << InputVector.size() << " bytes." << std::endl; vector_type::const_iterator it = InputVector.begin(); // creating const iterator for ( ; it != InputVector.end(); ++it) // iterate through InputVector { OutputVector.push_back(*it); // add the value pointed by 'it' to OutputVector } return 0; } stxxl-1.3.1/containers/test_iterators.cpp0000644000175000017500000002431111336517455020451 0ustar andreasandreas/*************************************************************************** * containers/test_iterators.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2007 Roman Dementiev * Copyright (C) 2009 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #include #include #include #include #include #include #define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100) template const char * _() { const char * start = strchr(STXXL_PRETTY_FUNCTION_NAME, '['); if (start == NULL) return "unknown"; else return start; } template void dump_iterator_info(I &) { STXXL_MSG(STXXL_PRETTY_FUNCTION_NAME); STXXL_MSG(" category: " << _::iterator_category>()); STXXL_MSG(" value_type: " << _::value_type>()); STXXL_MSG(" difference_type: " << _::difference_type>()); STXXL_MSG(" pointer: " << _::pointer>()); STXXL_MSG(" reference: " << _::reference>()); } template void dump_container_info(C &) { STXXL_MSG(STXXL_PRETTY_FUNCTION_NAME); STXXL_MSG(" value_type: " << _()); STXXL_MSG(" size_type: " << _()); STXXL_MSG(" difference_type: " << _()); STXXL_MSG(" pointer: " << _()); STXXL_MSG(" const_pointer: " << _()); STXXL_MSG(" reference: " << _()); STXXL_MSG(" const_reference: " << _()); STXXL_MSG(" iterator: " << _()); STXXL_MSG(" const_iterator: " << _()); } template struct modify { void operator () (T & obj) const { ++obj; } }; template bool test_inc_dec(Iterator it) { Iterator i = it; ++i; i++; --i; i--; assert(it == i); return it == i; } template bool test_inc_dec_random(Iterator it) { Iterator i = it; ++i; i = i + 2; i++; i += 3; --i; i = i - 3; i--; i -= 2; assert(it == i); return it == i; } template struct test_comparison_lt_gt { void operator () (IteratorA, IteratorB) { // operators <, <=, >=, > are not available in all iterator categories } }; template struct test_comparison_lt_gt { void operator () (IteratorA a, IteratorB b) { a < b; a <= b; a > b; a >= b; b < a; b <= a; b > a; b >= a; } }; template void test_comparison(IteratorA a, IteratorB b) { a == b; a != b; b == a; b != a; test_comparison_lt_gt::iterator_category>() (a, b); } template void test_operators(Iterator it) { *it; it.operator -> (); test_comparison(it, it); } template void test(svt & sv) { dump_container_info(sv); typedef const svt csvt; typedef typename svt::value_type value_type; sv[0] = 108; typename svt::iterator svi = sv.begin(); dump_iterator_info(svi); modify() (*svi); typename svt::const_iterator svci = sv.begin(); dump_iterator_info(svci); //modify()(*svci); // read-only typename csvt::iterator xsvi = sv.begin(); modify() (*xsvi); // test assignment svci = xsvi; //xsvi = svci; // not allowed typename csvt::const_iterator xsvci = sv.begin(); //modify()(*xsvci); // read-only // test comparison between const and non-const iterators test_comparison(svci, xsvi); // test increment/decrement test_inc_dec(svi); test_inc_dec(svci); test_inc_dec(xsvi); test_inc_dec(xsvci); // test operators test_operators(svi); test_operators(svci); test_operators(xsvi); test_operators(xsvci); // test forward iteration for (typename svt::iterator i = sv.begin(); i != sv.end(); ++i) ; /////////////////////////////////////////////////////////////////////////// csvt & csv = sv; //csv[0] = 108; // read-only //typename csvt::iterator csvi = csv.begin(); // read-only //modify()(*csvi); // read-only typename csvt::const_iterator csvci = csv.begin(); //modify()(*csvci); // read-only //typename svt::iterator xcsvi = csv.begin(); // read-only //modify()(*xcsvi); // read-only typename svt::const_iterator xcsvci = csv.begin(); //modify()(*csvci); // read-only // test increment/decrement test_inc_dec(csvci); test_inc_dec(xcsvci); // test operators test_operators(csvci); test_operators(xcsvci); // test forward iteration for (typename svt::const_iterator ci = sv.begin(); ci != sv.end(); ++ci) ; } template void test_reverse(svt & sv) { dump_container_info(sv); typedef const svt csvt; typedef typename svt::value_type value_type; sv[0] = 108; typename svt::reverse_iterator svi = sv.rbegin(); dump_iterator_info(svi); modify() (*svi); typename svt::const_reverse_iterator svci = sv.rbegin(); dump_iterator_info(svci); //modify()(*svci); // read-only typename csvt::reverse_iterator xsvi = sv.rbegin(); modify() (*xsvi); // test assignment svci = xsvi; //xsvi = svci; // not allowed typename csvt::const_reverse_iterator xsvci = sv.rbegin(); //modify()(*xsvci); // read-only #if !defined(__GNUG__) || (GCC_VERSION >= 40100) // test comparison between const and non-const iterators test_comparison(svci, xsvi); #endif // test increment/decrement test_inc_dec(svi); test_inc_dec(svci); test_inc_dec(xsvi); test_inc_dec(xsvci); // test operators test_operators(svi); test_operators(svci); test_operators(xsvi); test_operators(xsvci); // test forward iteration for (typename svt::reverse_iterator i = sv.rbegin(); i != sv.rend(); ++i) ; /////////////////////////////////////////////////////////////////////////// csvt & csv = sv; //csv[0] = 108; // read-only //typename csvt::reverse_iterator csvi = csv.rbegin(); // read-only //modify()(*csvi); // read-only typename csvt::const_reverse_iterator csvci = csv.rbegin(); //modify()(*csvci); // read-only //typename svt::reverse_iterator xcsvi = csv.rbegin(); // read-only //modify()(*xcsvi); // read-only typename svt::const_reverse_iterator xcsvci = csv.rbegin(); //modify()(*csvci); // read-only // test increment/decrement test_inc_dec(csvci); test_inc_dec(xcsvci); // test operators test_operators(csvci); test_operators(xcsvci); // test forward iteration #if !defined(__GNUG__) || (GCC_VERSION >= 40100) for (typename svt::const_reverse_iterator ci = sv.rbegin(); ci != sv.rend(); ++ci) ; #else for (typename svt::const_reverse_iterator ci = sv.rbegin(); ci != typename svt::const_reverse_iterator(sv.rend()); ++ci) ; #endif } template void test_random_access(svt & sv) { typename svt::const_iterator svci = sv.begin(); typename svt::iterator xsvi = sv.begin(); // test subtraction of const and non-const iterators svci - xsvi; xsvi - svci; // bracket operators svci[0]; xsvi[0]; //svci[0] = 1; // read-only xsvi[0] = 1; // test +, -, +=, -= test_inc_dec_random(svci); test_inc_dec_random(xsvi); } template void test_random_access_reverse(svt & sv) { typename svt::const_reverse_iterator svcri = sv.rbegin(); typename svt::reverse_iterator xsvri = sv.rbegin(); #if !defined(__GNUG__) || (GCC_VERSION >= 40100) // test subtraction of const and non-const iterators svcri - xsvri; xsvri - svcri; #endif // bracket operators svcri[0]; xsvri[0]; //svcri[0] = 1; // read-only xsvri[0] = 1; // test +, -, +=, -= test_inc_dec_random(svcri); test_inc_dec_random(xsvri); } typedef float key_type; typedef double data_type; struct cmp : public std::less { static key_type min_value() { return (std::numeric_limits::min)(); } static key_type max_value() { return (std::numeric_limits::max)(); } }; template <> struct modify > { void operator () (std::pair & obj) const { ++(obj.second); } }; int main() { std::vector V(8); test(V); test_reverse(V); test_random_access(V); test_random_access_reverse(V); stxxl::vector Vector(8); test(Vector); test_reverse(Vector); test_random_access(Vector); test_random_access_reverse(Vector); std::map M; M[4] = 8; M[15] = 16; M[23] = 42; test(M); test_reverse(M); #if !defined(__GNUG__) || (GCC_VERSION >= 30400) typedef stxxl::map map_type; map_type Map(4096 * 10, 4096 * 10); Map[4] = 8; Map[15] = 16; Map[23] = 42; test(Map); test_reverse(Map); #endif std::deque D(8); test(D); test_reverse(D); test_random_access(D); test_random_access_reverse(D); stxxl::deque Deque(8); test(Deque); test_reverse(Deque); test_random_access(Deque); test_random_access_reverse(Deque); return 0; } // vim: et:ts=4:sw=4 stxxl-1.3.1/containers/test_map.cpp0000644000175000017500000000643311531445437017214 0ustar andreasandreas/*************************************************************************** * containers/test_map.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2005, 2006 Roman Dementiev * Copyright (C) 2009 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #include #include #include #include typedef unsigned int key_type; typedef unsigned int data_type; struct cmp : public std::less { static key_type min_value() { return (std::numeric_limits::min)(); } static key_type max_value() { return (std::numeric_limits::max)(); } }; #define BLOCK_SIZE (32 * 1024) #define CACHE_SIZE (2 * 1024 * 1024 / BLOCK_SIZE) #define CACHE_ELEMENTS (BLOCK_SIZE * CACHE_SIZE / (sizeof(key_type) + sizeof(data_type))) typedef stxxl::map map_type; int main(int argc, char ** argv) { stxxl::stats_data stats_begin(*stxxl::stats::get_instance()); stxxl::stats_data stats_elapsed; STXXL_MSG(stats_begin); STXXL_MSG("Block size " << BLOCK_SIZE / 1024 << " KiB"); STXXL_MSG("Cache size " << (CACHE_SIZE * BLOCK_SIZE) / 1024 << " KiB"); int max_mult = 256; if (argc > 1) max_mult = atoi(argv[1]); for (int mult = 1; mult < max_mult; mult *= 2) { stats_begin = *stxxl::stats::get_instance(); const unsigned el = mult * (CACHE_ELEMENTS / 8); STXXL_MSG("Elements to insert " << el << " volume =" << (el * (sizeof(key_type) + sizeof(data_type))) / 1024 << " KiB"); map_type * DMap = new map_type(CACHE_SIZE * BLOCK_SIZE / 2, CACHE_SIZE * BLOCK_SIZE / 2); //map_type Map(CACHE_SIZE*BLOCK_SIZE/2,CACHE_SIZE*BLOCK_SIZE/2); map_type & Map = *DMap; for (unsigned i = 0; i < el; ++i) { Map[i] = i + 1; } stats_elapsed = stxxl::stats_data(*stxxl::stats::get_instance()) - stats_begin; double writes = double(stats_elapsed.get_writes()) / double(el); double logel = log(double(el)) / log(double(BLOCK_SIZE)); STXXL_MSG("Logs: writes " << writes << " logel " << logel << " writes/logel " << (writes / logel)); STXXL_MSG(stats_elapsed); stats_begin = *stxxl::stats::get_instance(); STXXL_MSG("Doing search"); unsigned queries = el; const map_type & ConstMap = Map; stxxl::random_number32 myrandom; for (unsigned i = 0; i < queries; ++i) { key_type key = myrandom() % el; map_type::const_iterator result = ConstMap.find(key); assert((*result).second == key + 1); } stats_elapsed = stxxl::stats_data(*stxxl::stats::get_instance()) - stats_begin; double reads = double(stats_elapsed.get_reads()) / logel; double readsperq = double(stats_elapsed.get_reads()) / queries; STXXL_MSG("reads/logel " << reads << " readsperq " << readsperq); STXXL_MSG(stats_elapsed); delete DMap; } return 0; } stxxl-1.3.1/containers/write_vector.cpp0000644000175000017500000001035211060745120020074 0ustar andreasandreas/*************************************************************************** * containers/write_vector.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2006 Roman Dementiev * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #include #include #include // efficiently writes data into an stxxl::vector with overlapping of I/O and // computation template class write_vector { typedef VectorType vector_type; typedef typename vector_type::size_type size_type; typedef typename vector_type::value_type value_type; typedef typename vector_type::block_type block_type; typedef typename vector_type::iterator ExtIterator; typedef typename vector_type::const_iterator ConstExtIterator; typedef stxxl::buf_ostream buf_ostream_type; vector_type & Vec; size_type RealSize; unsigned nbuffers; buf_ostream_type * outstream; public: write_vector(vector_type & Vec_, unsigned nbuffers_ // buffers to use for overlapping (>=2 recommended) ) : Vec(Vec_), RealSize(0), nbuffers(nbuffers_) { assert(Vec.empty()); // precondition: Vec is empty Vec.resize(2 * block_type::size); outstream = new buf_ostream_type(Vec.begin().bid(), nbuffers); } void push_back(const value_type & val) { ++RealSize; if (Vec.size() < RealSize) { // double the size of the array delete outstream; // flush overlap buffers Vec.resize(2 * Vec.size()); outstream = new buf_ostream_type((Vec.begin() + RealSize - 1).bid(), nbuffers); } ExtIterator it = Vec.begin() + RealSize - 1; if (it.block_offset() == 0) it.block_externally_updated(); // tells the vector that the block was modified) **outstream = val; ++(*outstream); } void finish() { ExtIterator out = Vec.begin() + RealSize; ConstExtIterator const_out = out; while (const_out.block_offset()) { **outstream = *const_out; // might cause I/Os for loading the page that ++const_out; // contains data beyond out ++(*outstream); } out.flush(); delete outstream; outstream = NULL; Vec.resize(RealSize); } virtual ~write_vector() { if (outstream) finish(); } }; typedef unsigned char my_type; // copies a file to another file using stxxl::syscall_file; using stxxl::file; int main(int argc, char * argv[]) { if (argc < 3) { std::cout << "Usage: " << argv[0] << " input_file output_file " << std::endl; return -1; } unlink(argv[2]); // delete output file syscall_file InputFile(argv[1], file::RDONLY); // Input file object syscall_file OutputFile(argv[2], file::RDWR | file::CREAT); // Output file object typedef stxxl::vector vector_type; std::cout << "Copying file " << argv[1] << " to " << argv[2] << std::endl; vector_type InputVector(&InputFile); // InputVector is mapped to InputFile vector_type OutputVector(&OutputFile); // OutputVector is mapped to OutputFile std::cout << "File " << argv[1] << " has size " << InputVector.size() << " bytes." << std::endl; vector_type::const_iterator it = InputVector.begin(); // creating const iterator write_vector Writer(OutputVector, 6); for ( ; it != InputVector.end(); ++it) // iterate through InputVector { Writer.push_back(*it); // add the value pointed by 'it' to OutputVector } Writer.finish(); // flush buffers return 0; } stxxl-1.3.1/containers/test_vector_sizes.cpp0000644000175000017500000000776611463541023021160 0ustar andreasandreas/*************************************************************************** * containers/test_vector_sizes.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2010 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #include #include typedef int my_type; typedef stxxl::VECTOR_GENERATOR::result vector_type; typedef vector_type::block_type block_type; void test_write(const char * fn, const char * ft, stxxl::unsigned_type sz, my_type ofs) { stxxl::file * f = stxxl::create_file(ft, fn, stxxl::file::CREAT | stxxl::file::DIRECT | stxxl::file::RDWR); { vector_type v(f); v.resize(sz); STXXL_MSG("writing " << v.size() << " elements"); for (stxxl::unsigned_type i = 0; i < v.size(); ++i) v[i] = ofs + i; } delete f; } template void test_rdwr(const char * fn, const char * ft, stxxl::unsigned_type sz, my_type ofs) { stxxl::file * f = stxxl::create_file(ft, fn, stxxl::file::DIRECT | stxxl::file::RDWR); { Vector v(f); STXXL_MSG("reading " << v.size() << " elements (RDWR)"); assert(v.size() == sz); for (stxxl::unsigned_type i = 0; i < v.size(); ++i) assert(v[i] == ofs + my_type(i)); } delete f; } template void test_rdonly(const char * fn, const char * ft, stxxl::unsigned_type sz, my_type ofs) { stxxl::file * f = stxxl::create_file(ft, fn, stxxl::file::DIRECT | stxxl::file::RDONLY); { Vector v(f); STXXL_MSG("reading " << v.size() << " elements (RDONLY)"); assert(v.size() == sz); for (stxxl::unsigned_type i = 0; i < v.size(); ++i) assert(v[i] == ofs + my_type(i)); } delete f; } void test(const char * fn, const char * ft, stxxl::unsigned_type sz, my_type ofs) { test_write(fn, ft, sz, ofs); test_rdwr(fn, ft, sz, ofs); test_rdwr(fn, ft, sz, ofs); test_rdonly(fn, ft, sz, ofs); test_rdonly(fn, ft, sz, ofs); } int main(int argc, char ** argv) { if (argc < 2) { std::cout << "Usage: " << argv[0] << " file [filetype]" << std::endl; return -1; } stxxl::config::get_instance(); const char * fn = argv[1]; const char * ft = "syscall"; if (argc >= 3) ft = argv[2]; stxxl::unsigned_type start_elements = 42 * block_type::size; STXXL_MSG("using " << ft << " file"); // multiple of block size test(fn, ft, start_elements, 100000000); // multiple of page size, but not block size test(fn, ft, start_elements + 4096, 200000000); // multiple of neither block size nor page size test(fn, ft, start_elements + 4096 + 23, 300000000); // truncate 1 byte { stxxl::syscall_file f(fn, stxxl::file::DIRECT | stxxl::file::RDWR); STXXL_MSG("file size is " << f.size() << " bytes"); f.set_size(f.size() - 1); STXXL_MSG("truncated to " << f.size() << " bytes"); } // will truncate after the last complete element test_rdwr(fn, ft, start_elements + 4096 + 23 - 1, 300000000); // truncate 1 more byte { stxxl::syscall_file f(fn, stxxl::file::DIRECT | stxxl::file::RDWR); STXXL_MSG("file size is " << f.size() << " bytes"); f.set_size(f.size() - 1); STXXL_MSG("truncated to " << f.size() << " bytes"); } // will not truncate test_rdonly(fn, ft, start_elements + 4096 + 23 - 2, 300000000); // check final size { stxxl::syscall_file f(fn, stxxl::file::DIRECT | stxxl::file::RDWR); STXXL_MSG("file size is " << f.size() << " bytes"); assert(f.size() == (start_elements + 4096 + 23 - 1) * sizeof(my_type) - 1); } } // vim: et:ts=4:sw=4 stxxl-1.3.1/containers/stack_benchmark.cpp0000644000175000017500000001422111535654452020514 0ustar andreasandreas/*************************************************************************** * containers/stack_benchmark.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2006 Roman Dementiev * Copyright (C) 2009, 2010 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ //! \example containers/stack_benchmark.cpp //! This is a benchmark mentioned in the paper //! R. Dementiev, L. Kettner, P. Sanders "STXXL: standard template library for XXL data sets" //! Software: Practice and Experience //! Volume 38, Issue 6, Pages 589-637, May 2008 //! DOI: 10.1002/spe.844 #include #include #include #define MEM_2_RESERVE (768 * 1024 * 1024) #ifndef BLOCK_SIZE #define BLOCK_SIZE (2 * 1024 * 1024) #endif #ifndef DISKS #define DISKS 4 #endif template struct my_record_ { char data[RECORD_SIZE]; my_record_() { memset(data, 0, sizeof(data)); } }; template inline std::ostream & operator << (std::ostream & o, const my_record_ &) { o << "."; return o; } template void benchmark_insert(stack_type & Stack, stxxl::int64 volume) { typedef typename stack_type::value_type value_type; STXXL_MSG("Record size: " << sizeof(value_type) << " bytes"); stxxl::int64 ops = volume / sizeof(value_type); value_type cur; // test whether top() returns an lvalue Stack.push(cur); Stack.top() = cur; Stack.pop(); stxxl::stats_data stats_begin(*stxxl::stats::get_instance()); stxxl::timer Timer; Timer.start(); for (stxxl::int64 i = 0; i < ops; ++i) { Stack.push(cur); } Timer.stop(); STXXL_MSG("Records in Stack: " << Stack.size()); if (ops != stxxl::int64(Stack.size())) { STXXL_MSG("Size does not match"); abort(); } STXXL_MSG("Insertions elapsed time: " << (Timer.mseconds() / 1000.) << " seconds : " << (double(volume) / (1024. * 1024. * Timer.mseconds() / 1000.)) << " MiB/s"); std::cout << stxxl::stats_data(*stxxl::stats::get_instance()) - stats_begin; } template void benchmark_delete(stack_type & Stack, stxxl::int64 volume) { typedef typename stack_type::value_type value_type; stxxl::int64 ops = volume / sizeof(value_type); value_type cur; stxxl::stats_data stats_begin(*stxxl::stats::get_instance()); stxxl::timer Timer; Timer.start(); for (stxxl::int64 i = 0; i < ops; ++i) { Stack.pop(); } Timer.stop(); STXXL_MSG("Records in Stack: " << Stack.size()); if (!Stack.empty()) { STXXL_MSG("Stack must be empty"); abort(); } STXXL_MSG("Deletions elapsed time: " << (Timer.mseconds() / 1000.) << " seconds : " << (double(volume) / (1024. * 1024. * Timer.mseconds() / 1000.)) << " MiB/s"); std::cout << stxxl::stats_data(*stxxl::stats::get_instance()) - stats_begin; } template void run_stxxl_growshrink2_stack(stxxl::int64 volume) { typedef typename stxxl::STACK_GENERATOR::result stack_type; typedef typename stack_type::block_type block_type; stxxl::read_write_pool pool(DISKS * 4, DISKS * 4); stack_type Stack(pool); benchmark_insert(Stack, volume); Stack.set_prefetch_aggr(DISKS * 8); benchmark_delete(Stack, volume); } template void run_stxxl_normal_stack(stxxl::int64 volume) { typedef typename stxxl::STACK_GENERATOR::result stack_type; stack_type Stack; benchmark_insert(Stack, volume); benchmark_delete(Stack, volume); } template void run_stl_stack(stxxl::int64 volume) { typedef std::stack stack_type; stack_type Stack; benchmark_insert(Stack, volume); benchmark_delete(Stack, volume); } int main(int argc, char * argv[]) { STXXL_MSG("stxxl::pq block size: " << BLOCK_SIZE << " bytes"); #ifdef STXXL_DIRECT_IO_OFF STXXL_MSG("STXXL_DIRECT_IO_OFF is defined"); #else STXXL_MSG("STXXL_DIRECT_IO_OFF is NOT defined"); #endif if (argc < 3) { STXXL_MSG("Usage: " << argv[0] << " variant volume"); STXXL_MSG("\t variant = 1: grow-shrink-stack2 with 4 byte records"); STXXL_MSG("\t variant = 2: grow-shrink-stack2 with 32 byte records"); STXXL_MSG("\t variant = 3: normal-stack with 4 byte records"); STXXL_MSG("\t variant = 4: normal-stack with 32 byte records"); STXXL_MSG("\t variant = 5: std::stack with 4 byte records"); STXXL_MSG("\t variant = 6: std::stack with 32 byte records"); STXXL_MSG("\t volume: in bytes"); return -1; } int variant = atoi(argv[1]); stxxl::int64 volume = stxxl::atoint64(argv[2]); STXXL_MSG("Allocating array with size " << MEM_2_RESERVE << " bytes to prevent file buffering."); int * array = new int[MEM_2_RESERVE / sizeof(int)]; std::fill(array, array + (MEM_2_RESERVE / sizeof(int)), 0); STXXL_MSG("Running variant: " << variant); STXXL_MSG("Data volume : " << volume << " bytes"); switch (variant) { case 1: run_stxxl_growshrink2_stack >(volume); break; case 2: run_stxxl_growshrink2_stack >(volume); break; case 3: run_stxxl_normal_stack >(volume); break; case 4: run_stxxl_normal_stack >(volume); break; case 5: run_stl_stack >(volume); break; case 6: run_stl_stack >(volume); break; default: STXXL_MSG("Unsupported variant " << variant); } delete[] array; } stxxl-1.3.1/containers/btree/0000755000175000017500000000000011536252421015761 5ustar andreasandreasstxxl-1.3.1/containers/btree/test_btree.cpp0000644000175000017500000001765611513575107020650 0ustar andreasandreas/*************************************************************************** * containers/btree/test_btree.cpp * * A very basic test * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2006 Roman Dementiev * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #include #include #include #include struct comp_type : public std::less { static int max_value() { return (std::numeric_limits::max)(); } }; typedef stxxl::btree::btree btree_type; std::ostream & operator << (std::ostream & o, const std::pair & obj) { o << obj.first << " " << obj.second; return o; } #define node_cache_size (25 * 1024 * 1024) #define leaf_cache_size (25 * 1024 * 1024) int main(int argc, char * argv[]) { if (argc < 2) { STXXL_MSG("Usage: " << argv[0] << " #ins"); return -1; } btree_type BTree1(node_cache_size, leaf_cache_size); unsigned nins = atoi(argv[1]); if (nins < 100) nins = 100; stxxl::random_number32 rnd; // .begin() .end() test BTree1[10] = 100.; btree_type::iterator begin = BTree1.begin(); btree_type::iterator end = BTree1.end(); assert(begin == BTree1.begin()); BTree1[5] = 50.; btree_type::iterator nbegin = BTree1.begin(); btree_type::iterator nend = BTree1.end(); assert(nbegin == BTree1.begin()); assert(begin != nbegin); assert(end == nend); assert(begin != end); assert(nbegin != end); assert(begin->first == 10); assert(begin->second == 100); assert(nbegin->first == 5); assert(nbegin->second == 50); BTree1[10] = 200.; assert(begin->second == 200.); btree_type::iterator it = BTree1.find(5); assert(it != BTree1.end()); assert(it->first == 5); assert(it->second == 50.); it = BTree1.find(6); assert(it == BTree1.end()); it = BTree1.find(1000); assert(it == BTree1.end()); int f = BTree1.erase(5); assert(f == 1); f = BTree1.erase(6); assert(f == 0); f = BTree1.erase(5); assert(f == 0); assert(BTree1.count(10) == 1); assert(BTree1.count(5) == 0); it = BTree1.insert(BTree1.begin(), std::pair(7, 70.)); assert(it->second == 70.); assert(BTree1.size() == 2); it = BTree1.insert(BTree1.begin(), std::pair(10, 300.)); assert(it->second == 200.); assert(BTree1.size() == 2); // test lower_bound it = BTree1.lower_bound(6); assert(it != BTree1.end()); assert(it->first == 7); it = BTree1.lower_bound(7); assert(it != BTree1.end()); assert(it->first == 7); it = BTree1.lower_bound(8); assert(it != BTree1.end()); assert(it->first == 10); it = BTree1.lower_bound(11); assert(it == BTree1.end()); // test upper_bound it = BTree1.upper_bound(6); assert(it != BTree1.end()); assert(it->first == 7); it = BTree1.upper_bound(7); assert(it != BTree1.end()); assert(it->first == 10); it = BTree1.upper_bound(8); assert(it != BTree1.end()); assert(it->first == 10); it = BTree1.upper_bound(10); assert(it == BTree1.end()); it = BTree1.upper_bound(11); assert(it == BTree1.end()); // test equal_range std::pair it_pair = BTree1.equal_range(1); assert(BTree1.find(7) == it_pair.first); assert(BTree1.find(7) == it_pair.second); it_pair = BTree1.equal_range(7); assert(BTree1.find(7) == it_pair.first); assert(BTree1.find(10) == it_pair.second); it_pair = BTree1.equal_range(8); assert(BTree1.find(10) == it_pair.first); assert(BTree1.find(10) == it_pair.second); it_pair = BTree1.equal_range(10); assert(BTree1.find(10) == it_pair.first); assert(BTree1.end() == it_pair.second); it_pair = BTree1.equal_range(11); assert(BTree1.end() == it_pair.first); assert(BTree1.end() == it_pair.second); // it = BTree1.lower_bound(0); BTree1.erase(it); assert(BTree1.size() == 1); BTree1.clear(); assert(BTree1.size() == 0); for (unsigned int i = 0; i < nins / 2; ++i) { BTree1[rnd() % nins] = 10.1; } STXXL_MSG("Size of map: " << BTree1.size()); BTree1.clear(); for (unsigned int i = 0; i < nins / 2; ++i) { BTree1[rnd() % nins] = 10.1; } STXXL_MSG("Size of map: " << BTree1.size()); btree_type BTree2(comp_type(), node_cache_size, leaf_cache_size); STXXL_MSG("Construction of BTree3 from BTree1 that has " << BTree1.size() << " elements"); btree_type BTree3(BTree1.begin(), BTree1.end(), comp_type(), node_cache_size, leaf_cache_size); assert(BTree3 == BTree1); STXXL_MSG("Bulk construction of BTree4 from BTree1 that has " << BTree1.size() << " elements"); btree_type BTree4(BTree1.begin(), BTree1.end(), comp_type(), node_cache_size, leaf_cache_size, true); STXXL_MSG("Size of BTree1: " << BTree1.size()); STXXL_MSG("Size of BTree4: " << BTree4.size()); assert(BTree4 == BTree1); assert(BTree3 == BTree4); BTree4.begin()->second = 0; assert(BTree3 != BTree4); assert(BTree4 < BTree3); BTree4.begin()->second = 1000; assert(BTree4 > BTree3); assert(BTree3 != BTree4); it = BTree4.begin(); ++it; STXXL_MSG("Size of Btree4 before erase: " << BTree4.size()); BTree4.erase(it, BTree4.end()); STXXL_MSG("Size of Btree4 after erase: " << BTree4.size()); assert(BTree4.size() == 1); STXXL_MSG("Size of Btree1 before erase: " << BTree1.size()); BTree1.erase(BTree1.begin(), BTree1.end()); STXXL_MSG("Size of Btree1 after erase: " << BTree1.size()); assert(BTree1.empty()); // a copy of BTree3 btree_type BTree5(BTree3.begin(), BTree3.end(), comp_type(), node_cache_size, leaf_cache_size, true); assert(BTree5 == BTree3); btree_type::iterator b3 = BTree3.begin(); btree_type::iterator b4 = BTree4.begin(); btree_type::iterator e3 = BTree3.end(); btree_type::iterator e4 = BTree4.end(); STXXL_MSG("Testing swapping operation (std::swap)"); std::swap(BTree4, BTree3); assert(b3 == BTree4.begin()); assert(b4 == BTree3.begin()); assert(e3 == BTree4.end()); assert(e4 == BTree3.end()); assert(BTree5 == BTree4); assert(BTree5 != BTree3); btree_type::const_iterator cb = BTree3.begin(); btree_type::const_iterator ce = BTree3.end(); const btree_type & CBTree3 = BTree3; cb = CBTree3.begin(); b3 == cb; b3 != cb; cb == b3; cb != b3; ce = CBTree3.end(); btree_type::const_iterator cit = CBTree3.find(0); cit = CBTree3.lower_bound(0); cit = CBTree3.upper_bound(0); std::pair cit_pair = CBTree3.equal_range(1); assert(CBTree3.max_size() >= CBTree3.size()); CBTree3.key_comp(); CBTree3.value_comp(); double sum = 0.0; STXXL_MSG(*stxxl::stats::get_instance()); stxxl::timer Timer2; Timer2.start(); cit = BTree5.begin(); for ( ; cit != BTree5.end(); ++cit) sum += cit->second; Timer2.stop(); STXXL_MSG("Scanning with const iterator: " << Timer2.mseconds() << " msec"); STXXL_MSG(*stxxl::stats::get_instance()); stxxl::timer Timer1; Timer1.start(); it = BTree5.begin(); for ( ; it != BTree5.end(); ++it) sum += it->second; Timer1.stop(); STXXL_MSG("Scanning with non const iterator: " << Timer1.mseconds() << " msec"); STXXL_MSG(*stxxl::stats::get_instance()); BTree5.disable_prefetching(); BTree5.enable_prefetching(); BTree5.prefetching_enabled(); assert(BTree5.prefetching_enabled()); STXXL_MSG("All tests passed successfully"); return 0; } stxxl-1.3.1/containers/btree/test_corr_insert_erase.cpp0000644000175000017500000000674611417070377023257 0ustar andreasandreas/*************************************************************************** * containers/btree/test_corr_insert_erase.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2006 Roman Dementiev * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #include #include #include #include #include struct comp_type : public std::less { static int max_value() { return (std::numeric_limits::max)(); } static int min_value() { return (std::numeric_limits::min)(); } }; typedef stxxl::btree::btree btree_type; //typedef stxxl::btree::btree btree_type; std::ostream & operator << (std::ostream & o, const std::pair & obj) { o << obj.first << " " << obj.second; return o; } struct rnd_gen { stxxl::random_number32 rnd; int operator () () { return (rnd() >> 2) * 3; } }; bool operator == (const std::pair & a, const std::pair & b) { return a.first == b.first; } int main(int argc, char * argv[]) { if (argc < 2) { STXXL_MSG("Usage: " << argv[0] << " #log_ins"); return -1; } const int log_nins = atoi(argv[1]); if (log_nins > 31) { STXXL_ERRMSG("This test can't do more than 2^31 operations, you requested 2^" << log_nins); return -1; } btree_type BTree(1024 * 128, 1024 * 128); const stxxl::uint64 nins = 1ULL << log_nins; stxxl::ran32State = time(NULL); stxxl::vector Values(nins); STXXL_MSG("Generating " << nins << " random values"); stxxl::generate(Values.begin(), Values.end(), rnd_gen(), 4); STXXL_MSG("Sorting the random values"); stxxl::sort(Values.begin(), Values.end(), comp_type(), 128 * 1024 * 1024); STXXL_MSG("Deleting unique values"); stxxl::vector::iterator NewEnd = std::unique(Values.begin(), Values.end()); Values.resize(NewEnd - Values.begin()); STXXL_MSG("Randomly permute input values"); stxxl::random_shuffle(Values.begin(), Values.end(), 128 * 1024 * 1024); stxxl::vector::const_iterator it = Values.begin(); STXXL_MSG("Inserting " << Values.size() << " random values into btree"); for ( ; it != Values.end(); ++it) BTree.insert(std::pair(*it, double(*it) + 1.0)); STXXL_MSG("Number of elements in btree: " << BTree.size()); STXXL_MSG("Searching " << Values.size() << " existing elements and erasing them"); stxxl::vector::const_iterator vIt = Values.begin(); for ( ; vIt != Values.end(); ++vIt) { btree_type::iterator bIt = BTree.find(*vIt); assert(bIt != BTree.end()); bool f = BTree.erase((*vIt) + 1); // erasing non-existent element assert(f == 0); f = BTree.erase(*vIt); // erasing existing element assert(f == 1); bIt = BTree.find(*vIt); // checking it is not there assert(bIt == BTree.end()); f = BTree.erase(*vIt); // trying to erase it again assert(f == 0); } assert(BTree.empty()); STXXL_MSG("Test passed."); return 0; } stxxl-1.3.1/containers/btree/test_corr_insert_find.cpp0000644000175000017500000000543011417070377023065 0ustar andreasandreas/*************************************************************************** * containers/btree/test_corr_insert_find.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2006 Roman Dementiev * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #include #include #include struct comp_type : public std::less { static int max_value() { return (std::numeric_limits::max)(); } static int min_value() { return (std::numeric_limits::min)(); } }; typedef stxxl::btree::btree btree_type; std::ostream & operator << (std::ostream & o, const std::pair & obj) { o << obj.first << " " << obj.second; return o; } struct rnd_gen { stxxl::random_number32 rnd; int operator () () { return (rnd() >> 2) * 3; } }; bool operator == (const std::pair & a, const std::pair & b) { return a.first == b.first; } int main(int argc, char * argv[]) { if (argc < 2) { STXXL_MSG("Usage: " << argv[0] << " #log_ins"); return -1; } const int log_nins = atoi(argv[1]); if (log_nins > 31) { STXXL_ERRMSG("This test can't do more than 2^31 operations, you requested 2^" << log_nins); return -1; } btree_type BTree(1024 * 128, 1024 * 128); const stxxl::uint64 nins = 1ULL << log_nins; stxxl::ran32State = time(NULL); stxxl::vector Values(nins); STXXL_MSG("Generating " << nins << " random values"); stxxl::generate(Values.begin(), Values.end(), rnd_gen(), 4); stxxl::vector::const_iterator it = Values.begin(); STXXL_MSG("Inserting " << nins << " random values into btree"); for ( ; it != Values.end(); ++it) BTree.insert(std::pair(*it, double(*it) + 1.0)); STXXL_MSG("Number of elements in btree: " << BTree.size()); STXXL_MSG("Searching " << nins << " existing elements"); stxxl::vector::const_iterator vIt = Values.begin(); for ( ; vIt != Values.end(); ++vIt) { btree_type::iterator bIt = BTree.find(*vIt); assert(bIt != BTree.end()); assert(bIt->first == *vIt); } STXXL_MSG("Searching " << nins << " non-existing elements"); stxxl::vector::const_iterator vIt1 = Values.begin(); for ( ; vIt1 != Values.end(); ++vIt1) { btree_type::iterator bIt = BTree.find((*vIt1) + 1); assert(bIt == BTree.end()); } STXXL_MSG("Test passed."); return 0; } stxxl-1.3.1/containers/btree/btree_uml.xmi0000644000175000017500000126046210622615152020470 0ustar andreasandreas umbrello uml modeller http://uml.sf.net 1.5.1 UnicodeUTF8
stxxl-1.3.1/containers/btree/test_const_scan.cpp0000644000175000017500000000707511031437521021663 0ustar andreasandreas/*************************************************************************** * containers/btree/test_const_scan.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2006 Roman Dementiev * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #include #include #include struct comp_type : public std::less { static int max_value() { return (std::numeric_limits::max)(); } }; #define NODE_BLOCK_SIZE 4096 #define LEAF_BLOCK_SIZE 128 * 1024 struct my_type { double data; char filler[24]; }; std::ostream & operator << (std::ostream & o, const my_type & obj) { o << " " << obj.data; return o; } std::ostream & operator << (std::ostream & o, const std::pair & obj) { o << obj.first << " " << obj.second; return o; } typedef stxxl::btree::btree btree_type; #define node_cache_size (25 * 1024 * 1024) #define leaf_cache_size (6 * LEAF_BLOCK_SIZE) void NC(btree_type & BTree) { double sum = 0; stxxl::timer Timer1; Timer1.start(); btree_type::iterator it = BTree.begin(); btree_type::iterator end = BTree.end(); for ( ; it != end; ++it) sum += it->second.data; Timer1.stop(); STXXL_MSG("Scanning with non const iterator: " << Timer1.mseconds() << " msec"); } void C(btree_type & BTree) { double sum = 0; stxxl::timer Timer1; Timer1.start(); btree_type::const_iterator it = BTree.begin(); btree_type::const_iterator end = BTree.end(); for ( ; it != end; ++it) sum += it->second.data; Timer1.stop(); STXXL_MSG("Scanning with const iterator: " << Timer1.mseconds() << " msec"); } int main(int argc, char * argv[]) { if (argc < 2) { STXXL_MSG("Usage: " << argv[0] << " #ins"); return -1; } const unsigned nins = atoi(argv[1]); STXXL_MSG("Data set size : " << nins * sizeof(std::pair) << " bytes"); STXXL_MSG("Node cache size: " << node_cache_size << " bytes"); STXXL_MSG("Leaf cache size: " << leaf_cache_size << " bytes"); //stxxl::random_number32 rnd; std::vector > Data(nins); for (unsigned int i = 0; i < nins; ++i) { Data[i].first = i; } { btree_type BTree1(Data.begin(), Data.end(), comp_type(), node_cache_size, leaf_cache_size, true); btree_type BTree2(Data.begin(), Data.end(), comp_type(), node_cache_size, leaf_cache_size, true); //STXXL_MSG(*stxxl::stats::get_instance()); C(BTree1); //STXXL_MSG(*stxxl::stats::get_instance()); NC(BTree2); //STXXL_MSG(*stxxl::stats::get_instance()); } { btree_type BTree1(Data.begin(), Data.end(), comp_type(), node_cache_size, leaf_cache_size, true); btree_type BTree2(Data.begin(), Data.end(), comp_type(), node_cache_size, leaf_cache_size, true); STXXL_MSG("Disabling prefetching"); BTree1.disable_prefetching(); BTree2.disable_prefetching(); //STXXL_MSG(*stxxl::stats::get_instance()); C(BTree1); //STXXL_MSG(*stxxl::stats::get_instance()); NC(BTree2); //STXXL_MSG(*stxxl::stats::get_instance()); } STXXL_MSG("All tests passed successfully"); return 0; } stxxl-1.3.1/containers/btree/Makefile0000644000175000017500000000322611251665137017432 0ustar andreasandreasinclude ../Makefile.common include ../../make.settings tests: $(TESTS_BTREE) # DEPENDENCIES = $(DEPENDENCIES) btree.h leaf.h iterator.h iterator_map.h node_cache.h STXXL_COMPILER_OPTIONS = $(STXXL_COMPILER_OPTIONS) -DSTXXL_VERBOSE_LEVEL=0 test_const_scan: test_const_scan.$(EXEEXT) test_const_scan.$(EXEEXT): $(DEPENDENCIES) test_const_scan.cpp $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c test_const_scan.cpp $(LINKER) test_const_scan.$(OBJEXT) $(OUT)test_const_scan.$(EXEEXT) $(STXXL_LINKER_OPTIONS) test_corr_insert_erase: test_corr_insert_erase.$(EXEEXT) test_corr_insert_erase.$(EXEEXT): $(DEPENDENCIES) test_corr_insert_erase.cpp $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c test_corr_insert_erase.cpp $(LINKER) test_corr_insert_erase.$(OBJEXT) $(OUT)test_corr_insert_erase.$(EXEEXT) $(STXXL_LINKER_OPTIONS) test_corr_insert_find: test_corr_insert_find.$(EXEEXT) test_corr_insert_find.$(EXEEXT): $(DEPENDENCIES) test_corr_insert_find.cpp $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c test_corr_insert_find.cpp $(LINKER) test_corr_insert_find.$(OBJEXT) $(OUT)test_corr_insert_find.$(EXEEXT) $(STXXL_LINKER_OPTIONS) test_corr_insert_scan: test_corr_insert_scan.$(EXEEXT) test_corr_insert_scan.$(EXEEXT): $(DEPENDENCIES) test_corr_insert_scan.cpp $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c test_corr_insert_scan.cpp $(LINKER) test_corr_insert_scan.$(OBJEXT) $(OUT)test_corr_insert_scan.$(EXEEXT) $(STXXL_LINKER_OPTIONS) test_btree: test_btree.$(EXEEXT) test_btree.$(EXEEXT): $(DEPENDENCIES) test_btree.cpp $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c test_btree.cpp $(LINKER) test_btree.$(OBJEXT) $(OUT)test_btree.$(EXEEXT) $(STXXL_LINKER_OPTIONS) clean: $(RM) $(CLEAN_TARGETS) stxxl-1.3.1/containers/btree/test_corr_insert_scan.cpp0000644000175000017500000000576211417070377023101 0ustar andreasandreas/*************************************************************************** * containers/btree/test_corr_insert_scan.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2006 Roman Dementiev * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #include #include #include #include struct comp_type : public std::less { static int max_value() { return (std::numeric_limits::max)(); } static int min_value() { return (std::numeric_limits::min)(); } }; typedef stxxl::btree::btree btree_type; //typedef stxxl::btree::btree btree_type; std::ostream & operator << (std::ostream & o, const std::pair & obj) { o << obj.first << " " << obj.second; return o; } struct rnd_gen { stxxl::random_number32 rnd; int operator () () { return (rnd() >> 2); } }; bool operator == (const std::pair & a, const std::pair & b) { return a.first == b.first; } int main(int argc, char * argv[]) { if (argc < 2) { STXXL_MSG("Usage: " << argv[0] << " #log_ins"); return -1; } const int log_nins = atoi(argv[1]); if (log_nins > 31) { STXXL_ERRMSG("This test can't do more than 2^31 operations, you requested 2^" << log_nins); return -1; } btree_type BTree(1024 * 128, 1024 * 128); const stxxl::uint64 nins = 1ULL << log_nins; stxxl::ran32State = time(NULL); stxxl::vector Values(nins); STXXL_MSG("Generating " << nins << " random values"); stxxl::generate(Values.begin(), Values.end(), rnd_gen(), 4); stxxl::vector::const_iterator it = Values.begin(); STXXL_MSG("Inserting " << nins << " random values into btree"); for ( ; it != Values.end(); ++it) BTree.insert(std::pair(*it, double(*it) + 1.0)); STXXL_MSG("Sorting the random values"); stxxl::sort(Values.begin(), Values.end(), comp_type(), 128 * 1024 * 1024); STXXL_MSG("Deleting unique values"); stxxl::vector::iterator NewEnd = std::unique(Values.begin(), Values.end()); Values.resize(NewEnd - Values.begin()); assert(BTree.size() == Values.size()); STXXL_MSG("Size without duplicates: " << Values.size()); STXXL_MSG("Comparing content"); stxxl::vector::const_iterator vIt = Values.begin(); btree_type::iterator bIt = BTree.begin(); for ( ; vIt != Values.end(); ++vIt, ++bIt) { assert(*vIt == bIt->first); assert(double(bIt->first) + 1.0 == bIt->second); assert(bIt != BTree.end()); } assert(bIt == BTree.end()); STXXL_MSG("Test passed."); return 0; } stxxl-1.3.1/containers/test_queue.cpp0000644000175000017500000001101211535151017017540 0ustar andreasandreas/*************************************************************************** * containers/test_queue.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2005 Roman Dementiev * Copyright (C) 2009 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #include #include typedef unsigned my_type; template void check(const q1type & q1, const q2type & q2) { assert(q1.empty() == q2.empty()); assert(q1.size() == q2.size()); if (!q1.empty()) { if (q1.front() != q2.front() || q1.back() != q2.back()) STXXL_MSG(q1.size() << ": (" << q1.front() << ", " << q1.back() << ") (" << q2.front() << ", " << q2.back() << ")" << (q1.front() == q2.front() ? "" : " FRONT")); assert(q1.front() == q2.front()); assert(q1.back() == q2.back()); } } int main() { #if 1 //stxxl::set_seed(424648671); // works fine with a single disk, fails with two disks STXXL_MSG("SEED=" << stxxl::get_next_seed()); stxxl::srandom_number32(stxxl::get_next_seed()); stxxl::random_number32_r rnd; #else //stxxl::ran32State = 1028675152; // fails with two disks STXXL_MSG("ran32State=" << stxxl::ran32State); stxxl::random_number32 rnd; #endif unsigned cnt; STXXL_MSG("Elements in a block: " << stxxl::queue::block_type::size); // FIXME: can this be raised to recommended (3, 2) without breaking "Testing special case 4" or any other tests? stxxl::queue xqueue(2, 2, -1); std::queue squeue; check(xqueue, squeue); STXXL_MSG("Testing special case 4"); cnt = stxxl::queue::block_type::size; while (cnt--) { my_type val = rnd(); xqueue.push(val); squeue.push(val); check(xqueue, squeue); } cnt = stxxl::queue::block_type::size; while (cnt--) { xqueue.pop(); squeue.pop(); check(xqueue, squeue); } STXXL_MSG("Testing other cases "); cnt = 100 * stxxl::queue::block_type::size; while (cnt--) { if ((cnt % 1000000) == 0) STXXL_MSG("Operations left: " << cnt << " queue size " << squeue.size()); int rndtmp = rnd() % 3; if (rndtmp > 0 || squeue.empty()) { my_type val = rnd(); xqueue.push(val); squeue.push(val); check(xqueue, squeue); } else { xqueue.pop(); squeue.pop(); check(xqueue, squeue); } } while (!squeue.empty()) { if ((cnt++ % 1000000) == 0) STXXL_MSG("Operations: " << cnt << " queue size " << squeue.size()); int rndtmp = rnd() % 4; if (rndtmp >= 3) { my_type val = rnd(); xqueue.push(val); squeue.push(val); check(xqueue, squeue); } else { xqueue.pop(); squeue.pop(); check(xqueue, squeue); } } cnt = 10 * stxxl::queue::block_type::size; while (cnt--) { if ((cnt % 1000000) == 0) STXXL_MSG("Operations left: " << cnt << " queue size " << squeue.size()); int rndtmp = rnd() % 3; if (rndtmp > 0 || squeue.empty()) { my_type val = rnd(); xqueue.push(val); squeue.push(val); check(xqueue, squeue); } else { xqueue.pop(); squeue.pop(); check(xqueue, squeue); } } typedef stxxl::queue::block_type block_type; stxxl::read_write_pool pool(5, 5); stxxl::queue xqueue1(pool, -1); std::queue squeue1; cnt = 10 * stxxl::queue::block_type::size; while (cnt--) { if ((cnt % 1000000) == 0) STXXL_MSG("Operations left: " << cnt << " queue size " << squeue1.size()); int rndtmp = rnd() % 3; if (rndtmp > 0 || squeue1.empty()) { my_type val = rnd(); xqueue1.push(val); squeue1.push(val); check(xqueue1, squeue1); } else { xqueue1.pop(); squeue1.pop(); check(xqueue1, squeue1); } } } stxxl-1.3.1/containers/Makefile.common0000644000175000017500000000115111500030337017574 0ustar andreasandreasTESTS = test_vector test_vector_export test_stack test_migr_stack test_many_stacks test_pqueue test_queue test_ext_merger test_ext_merger2 bench_pqueue copy_file test_deque test_iterators monotonic_pq pq_benchmark stack_benchmark write_vector write_vector2 benchmark_naive_matrix test_vector_sizes TESTS_MAP = test_map test_map_random TESTS_BDB = berkeley_db_benchmark TESTS_LEDASM = leda_sm_pq_benchmark leda_sm_stack_benchmark TESTS_TPIE = tpie_stack_benchmark TESTS_NON_MSVC = TESTS_BTREE = test_btree test_const_scan test_corr_insert_erase test_corr_insert_find test_corr_insert_scan LIB_SRC = stxxl-1.3.1/TODO0000644000175000017500000000457711504161427013220 0ustar andreasandreas* asynchronous pipelining (currently being developed in branch parallel_pipelining_integration) * replace build system, something with '$LIBNAME-config --libs --cflags ...' would be nice * if the stxxl disk files have been enlarged because more external memory was requested by the program, resize them afterwards to max(size_at_program_start, configured_size) https://sourceforge.net/forum/message.php?msg_id=4925158 * integrate unordered_map branch * allocation strategies: provide a method get_num_disks() and don't use stxxl::config::get_instance()->disks_number() inappropriately * implement recursion in stable_ksort and do not assume random key distribution, do sampling instead as a start, at least abort early if the expected size of a bucket is larger than the memory available to sort it * debug stable_ksort in depth, there are still some crashing cases left * continue using the new approach for STXXL_VERBOSE: $(CXX) -DSTXXL_VERBOSE_FOO=STXXL_VERBOSEx * check+fix all sorted_runs() calls to not cause write I/Os * on disk destruction, check whether all blocks had been deallocated before, i.e. free_bytes == disk_size * implement an allocator which looks at the available free space on disks when distributing blocks to disks, or does load-balancing depending on the given speed of the disks * implement new disk queuing strategy that supports NCQ, which is now widely available in HDDs/SSDs; probably most interesting for rather small block sizes (currently begin developed in branch kernelaio) * allow configuration of the block-managed disks using API calls, not only through the configuration file. * separate library sources and tests/benchmarks (e. g. to top level directories src/ and tests/) * abstract away block manager so every container can attach to a file. * overhead: stream::sorted_runs (which may be rather big) is copied into stream_runs_merger * overhead: stream::sorted_runs is copy-initialized from locally created runs * retry incomplete I/Os for all file types (currently only syscall) * iostats: add support for splitting I/Os and truncating reads at EOF * do not specify marginal properties such as allocation strategy as part of the template type. instead, make such properties dynamically configurable using run-time polymorphism, which would incur only a negligible running time overhead (one virtual function call per block). stxxl-1.3.1/io/0000755000175000017500000000000011536252421013122 5ustar andreasandreasstxxl-1.3.1/io/flushbuffers.cpp0000644000175000017500000001051211531445437016331 0ustar andreasandreas/*************************************************************************** * io/flushbuffers.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2002 Roman Dementiev * Copyright (C) 2008, 2009 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #include #include #include #ifndef BOOST_MSVC #include #endif using stxxl::timestamp; using stxxl::file; using stxxl::request_ptr; #ifdef BLOCK_ALIGN #undef BLOCK_ALIGN #endif #define BLOCK_ALIGN 4096 #define NOREAD //#define DO_ONLY_READ #define POLL_DELAY 1000 #define RAW_ACCESS //#define WATCH_TIMES #ifdef WATCH_TIMES void watch_times(request_ptr reqs[], unsigned n, double * out) { bool * finished = new bool[n]; unsigned count = 0; unsigned i = 0; for (i = 0; i < n; i++) finished[i] = false; while (count != n) { usleep(POLL_DELAY); i = 0; for (i = 0; i < n; i++) { if (!finished[i]) if (reqs[i]->poll()) { finished[i] = true; out[i] = timestamp(); count++; } } } delete[] finished; } void out_stat(double start, double end, double * times, unsigned n, const std::vector & names) { for (unsigned i = 0; i < n; i++) { std::cout << i << " " << names[i] << " took " << 100. * (times[i] - start) / (end - start) << " %" << std::endl; } } #endif #define MB (1024 * 1024) #define GB (1024 * 1024 * 1024) int main(int argc, char * argv[]) { if (argc < 2) { std::cout << "Usage: " << argv[0] << " length_in_GiB diskfile..." << std::endl; return -1; } stxxl::int64 offset = 0; stxxl::int64 end_offset = stxxl::int64(GB) * stxxl::int64(atoi(argv[1])); std::vector disks_arr; for (int ii = 2; ii < argc; ++ii) { std::cout << "# Add disk: " << argv[ii] << std::endl; disks_arr.push_back(argv[ii]); } const unsigned ndisks = disks_arr.size(); const unsigned buffer_size = 1024 * 1024 * 64; const unsigned buffer_size_int = buffer_size / sizeof(int); const unsigned chunks = 32; request_ptr * reqs = new request_ptr[ndisks * chunks]; file ** disks = new file *[ndisks]; int * buffer = (int *)stxxl::aligned_alloc(buffer_size * ndisks); #ifdef WATCH_TIMES double * r_finish_times = new double[ndisks]; double * w_finish_times = new double[ndisks]; #endif int count = (end_offset - offset) / buffer_size; unsigned i = 0, j = 0; for (i = 0; i < ndisks * buffer_size_int; i++) buffer[i] = i; for (i = 0; i < ndisks; i++) { disks[i] = new stxxl::syscall_file(disks_arr[i], file::CREAT | file::RDWR | file::DIRECT, i); } while (count--) { std::cout << "Disk offset " << offset / MB << " MiB "; double begin, end; begin = timestamp(); for (i = 0; i < ndisks; i++) { for (j = 0; j < chunks; j++) reqs[i * chunks + j] = disks[i]->aread(buffer + buffer_size_int * i + buffer_size_int * j / chunks, offset + buffer_size * j / chunks, buffer_size / chunks, stxxl::default_completion_handler()); } #ifdef WATCH_TIMES watch_times(reqs, ndisks, r_finish_times); #else wait_all(reqs, ndisks * chunks); #endif end = timestamp(); std::cout << int(double(buffer_size) / MB / (end - begin)) << " MiB/s" << std::endl; #ifdef WATCH_TIMES out_stat(begin, end, r_finish_times, ndisks, disks_arr); #endif offset += /* 4*stxxl::int64(GB); */ buffer_size; } for (i = 0; i < ndisks; i++) delete disks[i]; delete[] reqs; delete[] disks; stxxl::aligned_dealloc(buffer); #ifdef WATCH_TIMES delete[] r_finish_times; delete[] w_finish_times; #endif return 0; } stxxl-1.3.1/io/boostfd_file.cpp0000644000175000017500000001317511535550674016306 0ustar andreasandreas/*************************************************************************** * io/boostfd_file.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2006 Roman Dementiev * Copyright (C) 2009, 2010 Johannes Singler * Copyright (C) 2008, 2010 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #include #if STXXL_HAVE_BOOSTFD_FILE #include #include #include #include #include __STXXL_BEGIN_NAMESPACE void boostfd_file::serve(const request * req) throw (io_error) { scoped_mutex_lock fd_lock(fd_mutex); assert(req->get_file() == this); offset_type offset = req->get_offset(); void * buffer = req->get_buffer(); size_type bytes = req->get_size(); request::request_type type = req->get_type(); try { file_des.seek(offset, BOOST_IOS::beg); } catch (const std::exception & ex) { STXXL_THROW2(io_error, "Error doing seek() in boostfd_request::serve()" << " offset=" << offset << " this=" << this << " buffer=" << buffer << " bytes=" << bytes << " type=" << ((type == request::READ) ? "READ" : "WRITE") << " : " << ex.what()); } stats::scoped_read_write_timer read_write_timer(bytes, type == request::WRITE); if (type == request::READ) { try { std::streamsize rc = file_des.read((char *)buffer, bytes); if (rc != std::streamsize(bytes)) { STXXL_THROW2(io_error, " partial read: missing " << (bytes - rc) << " out of " << bytes << " bytes"); } } catch (const std::exception & ex) { STXXL_THROW2(io_error, "Error doing read() in boostfd_request::serve()" << " offset=" << offset << " this=" << this << " buffer=" << buffer << " bytes=" << bytes << " type=" << ((type == request::READ) ? "READ" : "WRITE") << " : " << ex.what()); } } else { try { std::streamsize rc = file_des.write((char *)buffer, bytes); if (rc != std::streamsize(bytes)) { STXXL_THROW2(io_error, " partial read: missing " << (bytes - rc) << " out of " << bytes << " bytes"); } } catch (const std::exception & ex) { STXXL_THROW2(io_error, "Error doing write() in boostfd_request::serve()" << " offset=" << offset << " this=" << this << " buffer=" << buffer << " bytes=" << bytes << " type=" << ((type == request::READ) ? "READ" : "WRITE") << " : " << ex.what()); } } } const char * boostfd_file::io_type() const { return "boostfd"; } boostfd_file::boostfd_file( const std::string & filename, int mode, int queue_id, int allocator_id) : disk_queued_file(queue_id, allocator_id), mode_(mode) { BOOST_IOS::openmode boostfd_mode; if (mode & RDONLY) { boostfd_mode = BOOST_IOS::in; } if (mode & WRONLY) { boostfd_mode = BOOST_IOS::out; } if (mode & RDWR) { boostfd_mode = BOOST_IOS::out | BOOST_IOS::in; } const boost::filesystem::path fspath(filename, boost::filesystem::native); if (mode & TRUNC) { if (boost::filesystem::exists(fspath)) { boost::filesystem::remove(fspath); boost::filesystem::ofstream f(fspath); f.close(); assert(boost::filesystem::exists(fspath)); } } if (mode & CREAT) { // need to be emulated: if (!boost::filesystem::exists(fspath)) { boost::filesystem::ofstream f(fspath); f.close(); assert(boost::filesystem::exists(fspath)); } } #ifndef STXXL_DIRECT_IO_OFF if (mode & DIRECT) { // direct mode not supported in Boost } #endif if (mode & SYNC) { // ??? } #if (BOOST_VERSION >= 104100) file_des.open(filename, boostfd_mode); // also compiles with earlier Boost versions, but differs semantically #else file_des.open(filename, boostfd_mode, boostfd_mode); #endif } boostfd_file::~boostfd_file() { scoped_mutex_lock fd_lock(fd_mutex); file_des.close(); } inline file::offset_type boostfd_file::_size() { return file_des.seek(0, BOOST_IOS::end); } file::offset_type boostfd_file::size() { scoped_mutex_lock fd_lock(fd_mutex); return _size(); } void boostfd_file::set_size(offset_type newsize) { scoped_mutex_lock fd_lock(fd_mutex); offset_type oldsize = _size(); file_des.seek(newsize, BOOST_IOS::beg); file_des.seek(0, BOOST_IOS::beg); // not important ? assert(_size() >= oldsize); } void boostfd_file::lock() { // FIXME: is there no locking possible/needed/... for boostfd? } __STXXL_END_NAMESPACE #endif // #if STXXL_HAVE_BOOSTFD_FILE // vim: et:ts=4:sw=4 stxxl-1.3.1/io/fileperblock_file.cpp0000644000175000017500000001013211535637446017300 0ustar andreasandreas/*************************************************************************** * io/fileperblock_file.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2008, 2009 Johannes Singler * Copyright (C) 2008 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #include #include #include #include #include #include #include #include #include #include __STXXL_BEGIN_NAMESPACE template fileperblock_file::fileperblock_file( const std::string & filename_prefix, int mode, int queue_id, int allocator_id) : disk_queued_file(queue_id, allocator_id), filename_prefix(filename_prefix), mode(mode), lock_file_created(false), lock_file(filename_prefix + "_fpb_lock", mode, queue_id) { } template fileperblock_file::~fileperblock_file() { if (lock_file_created) ::remove((filename_prefix + "_fpb_lock").c_str()); } template std::string fileperblock_file::filename_for_block(unsigned_type offset) { std::ostringstream name; //enough for 1 billion blocks name << filename_prefix << "_fpb_" << std::setw(20) << std::setfill('0') << offset; return name.str(); } template void fileperblock_file::serve(const request * req) throw (io_error) { assert(req->get_file() == this); base_file_type base_file(filename_for_block(req->get_offset()), mode, get_queue_id()); base_file.set_size(req->get_size()); request_ptr derived(new serving_request(default_completion_handler(), &base_file, req->get_buffer(), 0, req->get_size(), req->get_type())); request_ptr dummy = derived; derived->serve(); } template void fileperblock_file::lock() { if (!lock_file_created) { //create lock file and fill it with one page, an empty file cannot be locked const int page_size = BLOCK_ALIGN; void * one_page = aligned_alloc(page_size); lock_file.set_size(page_size); request_ptr r = lock_file.awrite(one_page, 0, page_size, default_completion_handler()); r->wait(); aligned_dealloc(one_page); lock_file_created = true; } lock_file.lock(); } template void fileperblock_file::discard(offset_type offset, offset_type length) { STXXL_UNUSED(length); #ifdef STXXL_FILEPERBLOCK_NO_DELETE ::truncate(filename_for_block(offset).c_str(), 0); #else ::remove(filename_for_block(offset).c_str()); #endif STXXL_VERBOSE2("discard " << offset << " + " << length); } template void fileperblock_file::export_files(offset_type offset, offset_type length, std::string filename) { std::string original(filename_for_block(offset)); filename.insert(0, original.substr(0, original.find_last_of("/") + 1)); ::remove(filename.c_str()); ::rename(original.c_str(), filename.c_str()); #ifndef BOOST_MSVC //TODO: implement on Windows ::truncate(filename.c_str(), length); #endif } template const char * fileperblock_file::io_type() const { return "fileperblock"; } //////////////////////////////////////////////////////////////////////////// template class fileperblock_file; #if STXXL_HAVE_MMAP_FILE template class fileperblock_file; #endif #if STXXL_HAVE_WINCALL_FILE template class fileperblock_file; #endif #if STXXL_HAVE_BOOSTFD_FILE template class fileperblock_file; #endif __STXXL_END_NAMESPACE stxxl-1.3.1/io/disk_queued_file.cpp0000644000175000017500000000256511535637446017154 0ustar andreasandreas/*************************************************************************** * io/disk_queued_file.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2008 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #include #include #include __STXXL_BEGIN_NAMESPACE request_ptr disk_queued_file::aread( void * buffer, offset_type pos, size_type bytes, const completion_handler & on_cmpl) { request_ptr req(new serving_request(on_cmpl, this, buffer, pos, bytes, request::READ)); disk_queues::get_instance()->add_request(req, get_queue_id()); return req; } request_ptr disk_queued_file::awrite( void * buffer, offset_type pos, size_type bytes, const completion_handler & on_cmpl) { request_ptr req(new serving_request(on_cmpl, this, buffer, pos, bytes, request::WRITE)); disk_queues::get_instance()->add_request(req, get_queue_id()); return req; } __STXXL_END_NAMESPACE // vim: et:ts=4:sw=4 stxxl-1.3.1/io/sd_test.cpp0000644000175000017500000000527611336456742015317 0ustar andreasandreas/*************************************************************************** * io/sd_test.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2002 Roman Dementiev * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ // Tests sim_disk file implementation // must be run on in-memory swap partition ! #include #include #include #include using stxxl::file; using stxxl::timestamp; int main() { const stxxl::int64 disk_size = stxxl::int64(1024 * 1024) * 1024 * 40; std::cout << sizeof(void *) << std::endl; const int block_size = 4 * 1024 * 1024; char * buffer = static_cast(stxxl::aligned_alloc(block_size)); memset(buffer, 0, block_size); const char * paths[2] = { "/tmp/data1", "/tmp/data2" }; stxxl::sim_disk_file file1(paths[0], file::CREAT | file::RDWR /* | file::DIRECT */, 0); file1.set_size(disk_size); stxxl::sim_disk_file file2(paths[1], file::CREAT | file::RDWR /* | file::DIRECT */, 1); file2.set_size(disk_size); unsigned i = 0; stxxl::int64 pos = 0; stxxl::request_ptr req; STXXL_MSG("Estimated time:" << block_size / double(AVERAGE_SPEED)); STXXL_MSG("Sequential write"); for (i = 0; i < 40; i++) { double begin = timestamp(); req = file1.awrite(buffer, pos, block_size, stxxl::default_completion_handler()); req->wait(); double end = timestamp(); STXXL_MSG("Pos: " << pos << " block_size:" << block_size << " time:" << (end - begin)); pos += 1024 * 1024 * 1024; } double sum = 0.; double sum2 = 0.; STXXL_MSG("Random write"); const unsigned int times = 80; for (i = 0; i < times; i++) { stxxl::random_number<> rnd; pos = rnd(disk_size / block_size) * block_size; double begin = timestamp(); req = file1.awrite(buffer, pos, block_size, stxxl::default_completion_handler()); req->wait(); double diff = timestamp() - begin; sum += diff; sum2 += diff * diff; STXXL_MSG("Pos: " << pos << " block_size:" << block_size << " time:" << (diff)); } sum = sum / double(times); sum2 = sum2 / double(times); assert(sum2 - sum * sum >= 0.0); double err = sqrt(sum2 - sum * sum); STXXL_MSG("Standard Deviation: " << err << " s, " << 100. * (err / sum) << " %"); stxxl::aligned_dealloc(buffer); unlink(paths[0]); unlink(paths[1]); return 0; } stxxl-1.3.1/io/request_queue_impl_worker.cpp0000644000175000017500000000305411535151017021134 0ustar andreasandreas/*************************************************************************** * io/request_queue_impl_worker.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2002-2005 Roman Dementiev * Copyright (C) 2008, 2009 Andreas Beckmann * Copyright (C) 2009 Johannes Singler * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #include #include #ifdef STXXL_BOOST_THREADS // Use Portable Boost threads #include #endif __STXXL_BEGIN_NAMESPACE void request_queue_impl_worker::start_thread(void * (*worker)(void *), void * arg, thread_type & t, state & s) #ifdef STXXL_BOOST_THREADS #endif { assert(s() == NOT_RUNNING); #ifdef STXXL_BOOST_THREADS t = new boost::thread(boost::bind(worker, arg)); #else check_pthread_call(pthread_create(&t, NULL, worker, arg)); #endif s.set_to(RUNNING); } void request_queue_impl_worker::stop_thread(thread_type & t, state & s, semaphore & sem) { assert(s() == RUNNING); s.set_to(TERMINATING); sem++; #ifdef STXXL_BOOST_THREADS t->join(); delete t; t = NULL; #else check_pthread_call(pthread_join(t, NULL)); #endif s.set_to(NOT_RUNNING); } __STXXL_END_NAMESPACE // vim: et:ts=4:sw=4 stxxl-1.3.1/io/gen_file.cpp0000644000175000017500000000412011531445437015401 0ustar andreasandreas/*************************************************************************** * algo/gen_file.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2002-2003 Roman Dementiev * Copyright (C) 2009 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #include #include #include struct my_type { typedef unsigned key_type; key_type _key; char _data[128 - sizeof(key_type)]; key_type key() const { return _key; } my_type() { } my_type(key_type __key) : _key(__key) { } static my_type min_value() { return my_type((std::numeric_limits::min)()); } static my_type max_value() { return my_type((std::numeric_limits::max)()); } }; bool operator < (const my_type & a, const my_type & b) { return a.key() < b.key(); } int main(int argc, char ** argv) { if (argc < 2) { std::cout << "Usage: " << argv[0] << " output_file" << std::endl; return -1; } const my_type::key_type max_key = 1 * 1024 * 1024; const unsigned int block_size = 1 * 1024 * 1024; const unsigned int records_in_block = block_size / sizeof(my_type); my_type * array = (my_type *)stxxl::aligned_alloc(block_size); memset(array, 0, block_size); stxxl::syscall_file f(argv[1], stxxl::file::CREAT | stxxl::file::RDWR); stxxl::request_ptr req; my_type::key_type cur_key = max_key; for (unsigned i = 0; i < max_key / records_in_block; i++) { for (unsigned j = 0; j < records_in_block; j++) array[j]._key = cur_key--; req = f.awrite((void *)array, stxxl::int64(i) * block_size, block_size, stxxl::default_completion_handler()); req->wait(); } stxxl::aligned_dealloc(array); return 0; } stxxl-1.3.1/io/syscall_file.cpp0000644000175000017500000000716611536140702016307 0ustar andreasandreas/*************************************************************************** * io/syscall_file.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2002 Roman Dementiev * Copyright (C) 2008, 2010 Andreas Beckmann * Copyright (C) 2010 Johannes Singler * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #include #include #include __STXXL_BEGIN_NAMESPACE #ifdef BOOST_MSVC #define lseek _lseeki64 #endif void syscall_file::serve(const request * req) throw (io_error) { scoped_mutex_lock fd_lock(fd_mutex); assert(req->get_file() == this); offset_type offset = req->get_offset(); char * buffer = static_cast(req->get_buffer()); size_type bytes = req->get_size(); request::request_type type = req->get_type(); stats::scoped_read_write_timer read_write_timer(bytes, type == request::WRITE); while (bytes > 0) { int_type rc; if ((rc = ::lseek(file_des, offset, SEEK_SET) < 0)) { STXXL_THROW2(io_error, " this=" << this << " call=::lseek(fd,offset,SEEK_SET)" << " path=" << filename << " fd=" << file_des << " offset=" << offset << " buffer=" << (void *)buffer << " bytes=" << bytes << " type=" << ((type == request::READ) ? "READ" : "WRITE") << " rc=" << rc); } if (type == request::READ) { if ((rc = ::read(file_des, buffer, bytes)) <= 0) { STXXL_THROW2(io_error, " this=" << this << " call=::read(fd,buffer,bytes)" << " path=" << filename << " fd=" << file_des << " offset=" << offset << " buffer=" << (void *)buffer << " bytes=" << bytes << " type=" << "READ" << " rc=" << rc); } bytes -= rc; offset += rc; buffer += rc; if (bytes > 0 && offset == this->_size()) { // read request extends past end-of-file // fill reminder with zeroes memset(buffer, 0, bytes); bytes = 0; } } else { if ((rc = ::write(file_des, buffer, bytes)) <= 0) { STXXL_THROW2(io_error, " this=" << this << " call=::write(fd,buffer,bytes)" << " path=" << filename << " fd=" << file_des << " offset=" << offset << " buffer=" << (void *)buffer << " bytes=" << bytes << " type=" << "WRITE" << " rc=" << rc); } bytes -= rc; offset += rc; buffer += rc; } } } const char * syscall_file::io_type() const { return "syscall"; } __STXXL_END_NAMESPACE // vim: et:ts=4:sw=4 stxxl-1.3.1/io/unittest.cpp0000644000175000017500000000463311046774020015513 0ustar andreasandreas/*************************************************************************** * io/unittest.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2007 Roman Dementiev * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #include #include #include #include struct my_handler { void operator () (stxxl::request * ptr) { STXXL_MSG("Request completed: " << ptr); } }; class IOLayerTest : public CppUnit::TestCase { CPPUNIT_TEST_SUITE(IOLayerTest); CPPUNIT_TEST(testIO); CPPUNIT_TEST_EXCEPTION(testIOException, stxxl::io_error); CPPUNIT_TEST_SUITE_END(); public: IOLayerTest(std::string name) : CppUnit::TestCase(name) { } IOLayerTest() { } void testIO() { const int size = 1024 * 384; char * buffer = static_cast(stxxl::aligned_alloc(size)); memset(buffer, 0, size); #ifdef BOOST_MSVC const char * paths[2] = { "data1", "data2" }; #else const char * paths[2] = { "/var/tmp/data1", "/var/tmp/data2" }; stxxl::mmap_file file1(paths[0], stxxl::file::CREAT | stxxl::file::RDWR, 0); file1.set_size(size * 1024); #endif stxxl::syscall_file file2(paths[1], stxxl::file::CREAT | stxxl::file::RDWR, 1); stxxl::request_ptr req[16]; unsigned i = 0; for ( ; i < 16; i++) req[i] = file2.awrite(buffer, i * size, size, my_handler()); stxxl::wait_all(req, 16); stxxl::aligned_dealloc(buffer); unlink(paths[0]); unlink(paths[1]); } void testIOException() { unlink("TestFile"); #ifdef BOOST_MSVC stxxl::mmap_file file1("TestFile", stxxl::file::RDWR, 0); #else stxxl::mmap_file file1("TestFile", stxxl::file::RDWR, 0); #endif } }; CPPUNIT_TEST_SUITE_REGISTRATION(IOLayerTest); int main() { CppUnit::TextUi::TestRunner runner; CppUnit::TestFactoryRegistry & registry = CppUnit::TestFactoryRegistry::getRegistry(); runner.addTest(registry.makeTest()); bool wasSuccessful = runner.run("", false); return wasSuccessful ? 0 : 1; } stxxl-1.3.1/io/request_with_waiters.cpp0000644000175000017500000000326311535561034020115 0ustar andreasandreas/*************************************************************************** * io/request_with_waiters.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2002 Roman Dementiev * Copyright (C) 2008 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #include #include #include __STXXL_BEGIN_NAMESPACE bool request_with_waiters::add_waiter(onoff_switch * sw) { // this lock needs to be obtained before poll(), otherwise a race // condition might occur: the state might change and notify_waiters() // could be called between poll() and insert() resulting in waiter sw // never being notified scoped_mutex_lock lock(waiters_mutex); if (poll()) // request already finished { return true; } waiters.insert(sw); return false; } void request_with_waiters::delete_waiter(onoff_switch * sw) { scoped_mutex_lock lock(waiters_mutex); waiters.erase(sw); } void request_with_waiters::notify_waiters() { scoped_mutex_lock lock(waiters_mutex); std::for_each(waiters.begin(), waiters.end(), std::mem_fun(&onoff_switch::on) _STXXL_FORCE_SEQUENTIAL); } /* int request_with_waiters::nwaiters() { scoped_mutex_lock lock(waiters_mutex); return waiters.size(); } */ __STXXL_END_NAMESPACE // vim: et:ts=4:sw=4 stxxl-1.3.1/io/test_io_sizes.cpp0000644000175000017500000000536511535151017016520 0ustar andreasandreas/*************************************************************************** * io/test_io_sizes.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2010 Johannes Singler * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #include #include #include //! \example io/test_io_sizes.cpp //! This tests the maximum chunk size that a file type can handle with a single request. int main(int argc, char ** argv) { if (argc < 4) { std::cout << "Usage: " << argv[0] << " filetype tempfile maxsize" << std::endl; return -1; } using stxxl::uint64; uint64 max_size = stxxl::atoint64(argv[3]); uint64 * buffer = (uint64 *)stxxl::aligned_alloc<4096>(max_size); try { stxxl::compat_unique_ptr::result file( stxxl::create_file(argv[1], argv[2], stxxl::file::CREAT | stxxl::file::RDWR | stxxl::file::DIRECT)); file->set_size(max_size); stxxl::request_ptr req; stxxl::stats_data stats1(*stxxl::stats::get_instance()); for (uint64 size = 4096; size < max_size; size *= 2) { //generate data for (uint64 i = 0; i < size / sizeof(uint64); ++i) buffer[i] = i; //write STXXL_MSG(stxxl::add_IEC_binary_multiplier(size, "B") << "are being written at once"); req = file->awrite(buffer, 0, size, stxxl::default_completion_handler()); wait_all(&req, 1); //fill with wrong data for (uint64 i = 0; i < size / sizeof(uint64); ++i) buffer[i] = 0xFFFFFFFFFFFFFFFFull; //read again STXXL_MSG(stxxl::add_IEC_binary_multiplier(size, "B") << "are being read at once"); req = file->aread(buffer, 0, size, stxxl::default_completion_handler()); wait_all(&req, 1); //check bool wrong = false; for (uint64 i = 0; i < size / sizeof(uint64); ++i) if (buffer[i] != i) { STXXL_ERRMSG("Read inconsistent data at position " << i * sizeof(uint64)); wrong = true; break; } if (wrong) break; } std::cout << stxxl::stats_data(*stxxl::stats::get_instance()) - stats1; file->remove(); } catch (stxxl::io_error e) { std::cerr << e.what() << std::endl; } stxxl::aligned_dealloc<4096>(buffer); return 0; } // vim: et:ts=4:sw=4 stxxl-1.3.1/io/request_with_state.cpp0000644000175000017500000000436411535564521017566 0ustar andreasandreas/*************************************************************************** * io/request_with_state.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2002, 2005, 2008 Roman Dementiev * Copyright (C) 2008 Andreas Beckmann * Copyright (C) 2009 Johannes Singler * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #include #include #include __STXXL_BEGIN_NAMESPACE request_with_state::~request_with_state() { STXXL_VERBOSE3("[" << static_cast(this) << "] request_with_state::~(), ref_cnt: " << ref_cnt); assert(_state() == DONE || _state() == READY2DIE); // if(_state() != DONE && _state()!= READY2DIE ) // STXXL_ERRMSG("WARNING: serious stxxl inconsistency: Request is being deleted while I/O not finished. "<< // "Please submit a bug report."); // _state.wait_for (READY2DIE); // does not make sense ? } void request_with_state::wait(bool measure_time) { STXXL_VERBOSE3("[" << static_cast(this) << "] request_with_state::wait()"); stats::scoped_wait_timer wait_timer(get_type() == READ ? stats::WAIT_OP_READ : stats::WAIT_OP_WRITE, measure_time); _state.wait_for(READY2DIE); check_errors(); } bool request_with_state::cancel() { STXXL_VERBOSE3("[" << static_cast(this) << "] request_with_state::cancel() " << file_ << " " << buffer << " " << offset); if (file_) { request_ptr rp(this); if (disk_queues::get_instance()->cancel_request(rp, file_->get_queue_id())) { _state.set_to(DONE); notify_waiters(); file_->delete_request_ref(); file_ = 0; _state.set_to(READY2DIE); return true; } } return false; } bool request_with_state::poll() { const request_state s = _state(); check_errors(); return s == DONE || s == READY2DIE; } __STXXL_END_NAMESPACE // vim: et:ts=4:sw=4 stxxl-1.3.1/io/test_cancel.cpp0000644000175000017500000000552311531445437016125 0ustar andreasandreas/*************************************************************************** * io/test_cancel.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2009-2011 Johannes Singler * Copyright (C) 2009 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #include #include //! \example io/test_cancel.cpp //! This tests the request cancelation mechanisms. using stxxl::file; struct print_completion { void operator () (stxxl::request * ptr) { std::cout << "Request completed: " << ptr << std::endl; } }; int main(int argc, char ** argv) { if (argc < 3) { std::cout << "Usage: " << argv[0] << " filetype tempfile" << std::endl; return -1; } const stxxl::uint64 size = 64 * 1024 * 1024, num_blocks = 16; char * buffer = (char *)stxxl::aligned_alloc<4096>(size); memset(buffer, 0, size); stxxl::compat_unique_ptr::result file( stxxl::create_file(argv[1], argv[2], stxxl::file::CREAT | stxxl::file::RDWR | stxxl::file::DIRECT)); file->set_size(num_blocks * size); stxxl::request_ptr req[num_blocks]; //without cancelation std::cout << "Posting " << num_blocks << " requests." << std::endl; stxxl::stats_data stats1(*stxxl::stats::get_instance()); unsigned i = 0; for ( ; i < num_blocks; i++) req[i] = file->awrite(buffer, i * size, size, print_completion()); wait_all(req, num_blocks); std::cout << stxxl::stats_data(*stxxl::stats::get_instance()) - stats1; //with cancelation std::cout << "Posting " << num_blocks << " requests." << std::endl; stxxl::stats_data stats2(*stxxl::stats::get_instance()); for (unsigned i = 0; i < num_blocks; i++) req[i] = file->awrite(buffer, i * size, size, print_completion()); //cancel first half std::cout << "Canceling first " << num_blocks / 2 << " requests." << std::endl; unsigned num_canceled = cancel_all(req, req + num_blocks / 2); std::cout << "Successfully canceled " << num_canceled << " requests." << std::endl; //cancel every second in second half for (unsigned i = num_blocks / 2; i < num_blocks; i += 2) { std::cout << "Canceling request " << &(*(req[i])) << std::endl; if (req[i]->cancel()) std::cout << "Request canceled: " << &(*(req[i])) << std::endl; else std::cout << "Request not canceled: " << &(*(req[i])) << std::endl; } wait_all(req, num_blocks); std::cout << stxxl::stats_data(*stxxl::stats::get_instance()) - stats2; stxxl::aligned_dealloc<4096>(buffer); return 0; } stxxl-1.3.1/io/benchmark_random_block_access.cpp0000644000175000017500000001600211535655573021630 0ustar andreasandreas/*************************************************************************** * io/benchmark_random_block_access.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2009 Johannes Singler * Copyright (C) 2009 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ /* example gnuplot command for the output of this program: (x-axis: offset in GiB, y-axis: bandwidth in MiB/s) plot \ "disk.log" using ($2/1024):($7) w l title "read", \ "disk.log" using ($2/1024):($4) w l title "write" */ #include #include #include #include #ifndef BOOST_MSVC #include #endif using stxxl::request_ptr; using stxxl::file; using stxxl::timestamp; #ifdef BLOCK_ALIGN #undef BLOCK_ALIGN #endif #define BLOCK_ALIGN 4096 #define KB (1024) #define MB (1024 * 1024) #define GB (1024 * 1024 * 1024) void usage(const char * argv0) { std::cout << "Usage: " << argv0 << " span block_size num_accesses [i][r][w]" << std::endl; std::cout << " 'span' is given in MiB" << std::endl; std::cout << " 'block_size' is given in KiB, must be a multiple of 4" << std::endl; std::cout << " (only a few block sizes are compiled in)" << std::endl; std::cout << " [i]nitialize, [r]ead, and/or [w]rite (one string)" << std::endl; exit(-1); } struct print_number { int n; print_number(int n) : n(n) { } void operator () (stxxl::request_ptr) { //std::cout << n << " " << std::flush; } }; template void run_test(stxxl::int64 span, stxxl::int64 num_blocks, bool do_init, bool do_read, bool do_write) { const unsigned raw_block_size = BlockSize; typedef stxxl::typed_block block_type; typedef stxxl::BID BID_type; stxxl::int64 num_blocks_in_span = stxxl::div_ceil(span, raw_block_size); num_blocks = stxxl::STXXL_MIN(num_blocks, num_blocks_in_span); block_type * buffer = new block_type; request_ptr * reqs = new request_ptr[num_blocks_in_span]; std::vector blocks; //touch data, so it is actually allocated try { STXXL_DEFAULT_ALLOC_STRATEGY alloc; blocks.resize(num_blocks_in_span); stxxl::block_manager::get_instance()->new_blocks(alloc, blocks.begin(), blocks.end()); std::cout << "# Span size: " << stxxl::add_IEC_binary_multiplier(span, "B") << " (" << num_blocks_in_span << " blocks of " << stxxl::add_IEC_binary_multiplier(raw_block_size, "B") << ")" << std::endl; double begin, end, elapsed; if (do_init) { begin = timestamp(); std::cout << "First fill up space by writing sequentially..." << std::endl; for (unsigned j = 0; j < num_blocks_in_span; j++) reqs[j] = buffer->write(blocks[j]); wait_all(reqs, num_blocks_in_span); end = timestamp(); elapsed = end - begin; std::cout << "Written " << std::setw(12) << num_blocks_in_span << " blocks in " << std::fixed << std::setw(9) << std::setprecision(2) << elapsed << " seconds: " << std::setw(9) << std::setprecision(1) << (double(num_blocks_in_span) / elapsed) << " blocks/s " << std::setw(7) << std::setprecision(1) << (double(num_blocks_in_span * raw_block_size) / MB / elapsed) << " MiB/s write " << std::endl; } std::cout << "Random block access..." << std::endl; srand(time(NULL)); std::random_shuffle(blocks.begin(), blocks.end()); begin = timestamp(); if (do_read) { for (unsigned j = 0; j < num_blocks; j++) reqs[j] = buffer->read(blocks[j], print_number(j)); wait_all(reqs, num_blocks); end = timestamp(); elapsed = end - begin; std::cout << "Read " << num_blocks << " blocks in " << std::fixed << std::setw(5) << std::setprecision(2) << elapsed << " seconds: " << std::setw(5) << std::setprecision(1) << (double(num_blocks) / elapsed) << " blocks/s " << std::setw(5) << std::setprecision(1) << (double(num_blocks * raw_block_size) / MB / elapsed) << " MiB/s read" << std::endl; } std::random_shuffle(blocks.begin(), blocks.end()); begin = timestamp(); if (do_write) { for (unsigned j = 0; j < num_blocks; j++) reqs[j] = buffer->write(blocks[j], print_number(j)); wait_all(reqs, num_blocks); end = timestamp(); elapsed = end - begin; std::cout << "Written " << num_blocks << " blocks in " << std::fixed << std::setw(5) << std::setprecision(2) << elapsed << " seconds: " << std::setw(5) << std::setprecision(1) << (double(num_blocks) / elapsed) << " blocks/s " << std::setw(5) << std::setprecision(1) << (double(num_blocks * raw_block_size) / MB / elapsed) << " MiB/s write " << std::endl; } } catch (const std::exception & ex) { std::cout << std::endl; STXXL_ERRMSG(ex.what()); } //stxxl::block_manager::get_instance()->delete_blocks(blocks.begin(), blocks.end()); delete[] reqs; delete buffer; } int main(int argc, char * argv[]) { if (argc < 4) usage(argv[0]); stxxl::int64 span = stxxl::int64(MB) * stxxl::int64(atoi(argv[1])); unsigned block_size = atoi(argv[2]); stxxl::int64 num_blocks = stxxl::int64(atoi(argv[3])); bool do_init = false, do_read = false, do_write = false; if (argc == 5 && (strstr(argv[4], "i") != NULL)) do_init = true; if (argc == 5 && (strstr(argv[4], "r") != NULL)) do_read = true; if (argc == 5 && (strstr(argv[4], "w") != NULL)) do_write = true; switch (block_size) { #define run(bs) run_test(span, num_blocks, do_init, do_read, do_write) case 4: run(4 * KB); break; case 8: run(8 * KB); break; case 16: run(16 * KB); break; case 32: run(32 * KB); break; case 64: run(64 * KB); break; case 128: run(128 * KB); break; case 256: run(256 * KB); break; case 512: run(512 * KB); break; case 1024: run(1024 * KB); break; case 2048: run(2048 * KB); break; case 4096: run(4096 * KB); break; default: std::cerr << "unsupported block_size " << block_size << std::endl; #undef run } return 0; } // vim: et:ts=4:sw=4 stxxl-1.3.1/io/iostats.cpp0000644000175000017500000003011111535151017015306 0ustar andreasandreas/*************************************************************************** * io/iostats.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2002-2004 Roman Dementiev * Copyright (C) 2008-2010 Andreas Beckmann * Copyright (C) 2009, 2010 Johannes Singler * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #include #include #include #include #include #include __STXXL_BEGIN_NAMESPACE stats::stats() : reads(0), writes(0), volume_read(0), volume_written(0), c_reads(0), c_writes(0), c_volume_read(0), c_volume_written(0), t_reads(0.0), t_writes(0.0), p_reads(0.0), p_writes(0.0), p_begin_read(0.0), p_begin_write(0.0), p_ios(0.0), p_begin_io(0.0), t_waits(0.0), p_waits(0.0), p_begin_wait(0.0), t_wait_read(0.0), p_wait_read(0.0), p_begin_wait_read(0.0), t_wait_write(0.0), p_wait_write(0.0), p_begin_wait_write(0.0), acc_reads(0), acc_writes(0), acc_ios(0), acc_waits(0), acc_wait_read(0), acc_wait_write(0), last_reset(timestamp()) { } #ifndef STXXL_IO_STATS_RESET_FORBIDDEN void stats::reset() { { scoped_mutex_lock ReadLock(read_mutex); //assert(acc_reads == 0); if (acc_reads) STXXL_ERRMSG("Warning: " << acc_reads << " read(s) not yet finished"); reads = 0; volume_read = 0; c_reads = 0; c_volume_read = 0; t_reads = 0; p_reads = 0.0; } { scoped_mutex_lock WriteLock(write_mutex); //assert(acc_writes == 0); if (acc_writes) STXXL_ERRMSG("Warning: " << acc_writes << " write(s) not yet finished"); writes = 0; volume_written = 0; c_writes = 0; c_volume_written = 0; t_writes = 0.0; p_writes = 0.0; } { scoped_mutex_lock IOLock(io_mutex); //assert(acc_ios == 0); if (acc_ios) STXXL_ERRMSG("Warning: " << acc_ios << " io(s) not yet finished"); p_ios = 0.0; } { scoped_mutex_lock WaitLock(wait_mutex); //assert(acc_waits == 0); if (acc_waits) STXXL_ERRMSG("Warning: " << acc_waits << " wait(s) not yet finished"); t_waits = 0.0; p_waits = 0.0; t_wait_read = 0.0; p_wait_read = 0.0; t_wait_write = 0.0; p_wait_write = 0.0; } last_reset = timestamp(); } #endif #if STXXL_IO_STATS void stats::write_started(unsigned_type size_, double now) { if (now == 0.0) now = timestamp(); { scoped_mutex_lock WriteLock(write_mutex); ++writes; volume_written += size_; double diff = now - p_begin_write; t_writes += double(acc_writes) * diff; p_begin_write = now; p_writes += (acc_writes++) ? diff : 0.0; } { scoped_mutex_lock IOLock(io_mutex); double diff = now - p_begin_io; p_ios += (acc_ios++) ? diff : 0.0; p_begin_io = now; } } void stats::write_canceled(unsigned_type size_) { { scoped_mutex_lock WriteLock(write_mutex); --writes; volume_written -= size_; } write_finished(); } void stats::write_finished() { double now = timestamp(); { scoped_mutex_lock WriteLock(write_mutex); double diff = now - p_begin_write; t_writes += double(acc_writes) * diff; p_begin_write = now; p_writes += (acc_writes--) ? diff : 0.0; } { scoped_mutex_lock IOLock(io_mutex); double diff = now - p_begin_io; p_ios += (acc_ios--) ? diff : 0.0; p_begin_io = now; } } void stats::write_cached(unsigned_type size_) { scoped_mutex_lock WriteLock(write_mutex); ++c_writes; c_volume_written += size_; } void stats::read_started(unsigned_type size_, double now) { if (now == 0.0) now = timestamp(); { scoped_mutex_lock ReadLock(read_mutex); ++reads; volume_read += size_; double diff = now - p_begin_read; t_reads += double(acc_reads) * diff; p_begin_read = now; p_reads += (acc_reads++) ? diff : 0.0; } { scoped_mutex_lock IOLock(io_mutex); double diff = now - p_begin_io; p_ios += (acc_ios++) ? diff : 0.0; p_begin_io = now; } } void stats::read_canceled(unsigned_type size_) { { scoped_mutex_lock ReadLock(read_mutex); --reads; volume_read -= size_; } read_finished(); } void stats::read_finished() { double now = timestamp(); { scoped_mutex_lock ReadLock(read_mutex); double diff = now - p_begin_read; t_reads += double(acc_reads) * diff; p_begin_read = now; p_reads += (acc_reads--) ? diff : 0.0; } { scoped_mutex_lock IOLock(io_mutex); double diff = now - p_begin_io; p_ios += (acc_ios--) ? diff : 0.0; p_begin_io = now; } } void stats::read_cached(unsigned_type size_) { scoped_mutex_lock ReadLock(read_mutex); ++c_reads; c_volume_read += size_; } #endif #ifndef STXXL_DO_NOT_COUNT_WAIT_TIME void stats::wait_started(wait_op_type wait_op) { double now = timestamp(); { scoped_mutex_lock WaitLock(wait_mutex); double diff = now - p_begin_wait; t_waits += double(acc_waits) * diff; p_begin_wait = now; p_waits += (acc_waits++) ? diff : 0.0; if (wait_op == WAIT_OP_READ) { diff = now - p_begin_wait_read; t_wait_read += double(acc_wait_read) * diff; p_begin_wait_read = now; p_wait_read += (acc_wait_read++) ? diff : 0.0; } else /* if (wait_op == WAIT_OP_WRITE) */ { // wait_any() is only used from write_pool and buffered_writer, so account WAIT_OP_ANY for WAIT_OP_WRITE, too diff = now - p_begin_wait_write; t_wait_write += double(acc_wait_write) * diff; p_begin_wait_write = now; p_wait_write += (acc_wait_write++) ? diff : 0.0; } } } void stats::wait_finished(wait_op_type wait_op) { double now = timestamp(); { scoped_mutex_lock WaitLock(wait_mutex); double diff = now - p_begin_wait; t_waits += double(acc_waits) * diff; p_begin_wait = now; p_waits += (acc_waits--) ? diff : 0.0; if (wait_op == WAIT_OP_READ) { double diff = now - p_begin_wait_read; t_wait_read += double(acc_wait_read) * diff; p_begin_wait_read = now; p_wait_read += (acc_wait_read--) ? diff : 0.0; } else /* if (wait_op == WAIT_OP_WRITE) */ { double diff = now - p_begin_wait_write; t_wait_write += double(acc_wait_write) * diff; p_begin_wait_write = now; p_wait_write += (acc_wait_write--) ? diff : 0.0; } #ifdef STXXL_WAIT_LOG_ENABLED std::ofstream * waitlog = stxxl::logger::get_instance()->waitlog_stream(); if (waitlog) *waitlog << (now - last_reset) << "\t" << ((wait_op == WAIT_OP_READ) ? diff : 0.0) << "\t" << ((wait_op != WAIT_OP_READ) ? diff : 0.0) << "\t" << t_wait_read << "\t" << t_wait_write << std::endl << std::flush; #endif } } #endif void stats::_reset_io_wait_time() { #ifndef STXXL_DO_NOT_COUNT_WAIT_TIME { scoped_mutex_lock WaitLock(wait_mutex); //assert(acc_waits == 0); if (acc_waits) STXXL_ERRMSG("Warning: " << acc_waits << " wait(s) not yet finished"); t_waits = 0.0; p_waits = 0.0; } #endif } std::string format_with_SI_IEC_unit_multiplier(uint64 number, const char * unit, int multiplier) { // may not overflow, std::numeric_limits::max() == 16 EB static const char * endings[] = { "", "k", "M", "G", "T", "P", "E" }; static const char * binary_endings[] = { "", "Ki", "Mi", "Gi", "Ti", "Pi", "Ei" }; std::ostringstream out; out << number << ' '; int scale = 0; double number_d = number; double multiplier_d = multiplier; while (number_d >= multiplier_d) { number_d /= multiplier_d; ++scale; } if (scale > 0) out << '(' << std::fixed << std::setprecision(3) << number_d << ' ' << (multiplier == 1024 ? binary_endings[scale] : endings[scale]) << (unit ? unit : "") << ") "; else if (unit && *unit) out << unit << ' '; return out.str(); } std::ostream & operator << (std::ostream & o, const stats_data & s) { #define hr add_IEC_binary_multiplier o << "STXXL I/O statistics" << std::endl; #if STXXL_IO_STATS o << " total number of reads : " << hr(s.get_reads()) << std::endl; o << " average block size (read) : " << hr(s.get_reads() ? s.get_read_volume() / s.get_reads() : 0, "B") << std::endl; o << " number of bytes read from disks : " << hr(s.get_read_volume(), "B") << std::endl; o << " time spent in serving all read requests : " << s.get_read_time() << " s" << " @ " << (s.get_read_volume() / 1048576.0 / s.get_read_time()) << " MiB/s" << std::endl; o << " time spent in reading (parallel read time) : " << s.get_pread_time() << " s" << " @ " << (s.get_read_volume() / 1048576.0 / s.get_pread_time()) << " MiB/s" << std::endl; if (s.get_cached_reads()) { o << " total number of cached reads : " << hr(s.get_cached_reads()) << std::endl; o << " average block size (cached read) : " << hr(s.get_cached_read_volume() / s.get_cached_reads(), "B") << std::endl; o << " number of bytes read from cache : " << hr(s.get_cached_read_volume(), "B") << std::endl; } if (s.get_cached_writes()) { o << " total number of cached writes : " << hr(s.get_cached_writes()) << std::endl; o << " average block size (cached write) : " << hr(s.get_cached_written_volume() / s.get_cached_writes(), "B") << std::endl; o << " number of bytes written to cache : " << hr(s.get_cached_written_volume(), "B") << std::endl; } o << " total number of writes : " << hr(s.get_writes()) << std::endl; o << " average block size (write) : " << hr(s.get_writes() ? s.get_written_volume() / s.get_writes() : 0, "B") << std::endl; o << " number of bytes written to disks : " << hr(s.get_written_volume(), "B") << std::endl; o << " time spent in serving all write requests : " << s.get_write_time() << " s" << " @ " << (s.get_written_volume() / 1048576.0 / s.get_write_time()) << " MiB/s" << std::endl; o << " time spent in writing (parallel write time): " << s.get_pwrite_time() << " s" << " @ " << (s.get_written_volume() / 1048576.0 / s.get_pwrite_time()) << " MiB/s" << std::endl; o << " time spent in I/O (parallel I/O time) : " << s.get_pio_time() << " s" << " @ " << ((s.get_read_volume() + s.get_written_volume()) / 1048576.0 / s.get_pio_time()) << " MiB/s" << std::endl; #else o << " n/a" << std::endl; #endif #ifndef STXXL_DO_NOT_COUNT_WAIT_TIME o << " I/O wait time : " << s.get_io_wait_time() << " s" << std::endl; if (s.get_wait_read_time() != 0.0) o << " I/O wait4read time : " << s.get_wait_read_time() << " s" << std::endl; if (s.get_wait_write_time() != 0.0) o << " I/O wait4write time : " << s.get_wait_write_time() << " s" << std::endl; #endif o << " Time since the last reset : " << s.get_elapsed_time() << " s" << std::endl; return o; #undef hr } __STXXL_END_NAMESPACE // vim: et:ts=4:sw=4 stxxl-1.3.1/io/benchmark_disks.cpp0000644000175000017500000004104311531445437016765 0ustar andreasandreas/*************************************************************************** * io/benchmark_disks.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2002-2003 Roman Dementiev * Copyright (C) 2007-2011 Andreas Beckmann * Copyright (C) 2009 Johannes Singler * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ /* example gnuplot command for the output of this program: (x-axis: disk offset in GiB, y-axis: bandwidth in MiB/s) plot \ "disk.log" using ($3/1024):($14) w l title "read", \ "disk.log" using ($3/1024):($7) w l title "write" */ #include #include #include #include #include #include using stxxl::request_ptr; using stxxl::file; using stxxl::timer; using stxxl::timestamp; #ifdef BLOCK_ALIGN #undef BLOCK_ALIGN #endif #define BLOCK_ALIGN 4096 //#define NOREAD //#define DO_ONLY_READ #define POLL_DELAY 1000 #define RAW_ACCESS //#define WATCH_TIMES #ifdef BOOST_MSVC const char * default_file_type = "wincall"; #else const char * default_file_type = "syscall"; #endif #ifdef WATCH_TIMES void watch_times(request_ptr reqs[], unsigned n, double * out) { bool * finished = new bool[n]; unsigned count = 0; for (unsigned i = 0; i < n; i++) finished[i] = false; while (count != n) { usleep(POLL_DELAY); unsigned i = 0; for (i = 0; i < n; i++) { if (!finished[i]) if (reqs[i]->poll()) { finished[i] = true; out[i] = timestamp(); count++; } } } delete[] finished; } void out_stat(double start, double end, double * times, unsigned n, const std::vector & names) { for (unsigned i = 0; i < n; i++) { std::cout << i << " " << names[i] << " took " << 100. * (times[i] - start) / (end - start) << " %" << std::endl; } } #endif #define MB (1024 * 1024) #define GB (1024 * 1024 * 1024) void usage(const char * argv0) { std::cout << "Usage: " << argv0 << " [options] offset length [block_size [batch_size]] [r|v|w] [--] diskfile..." << std::endl; std::cout << "Options:\n" #ifdef RAW_ACCESS " --no-direct open files without O_DIRECT\n" #endif " --sync open files with O_SYNC|O_DSYNC|O_RSYNC\n" " --file-type=syscall|mmap|wincall|boostfd|... default: " << default_file_type << "\n" " --resize resize the file size after opening,\n" " needed e.g. for creating mmap files\n" << std::endl; std::cout << " starting 'offset' and 'length' are given in GiB," << std::endl; std::cout << " 'block_size' (default 8) in MiB (in B if it has a suffix B)," << std::endl; std::cout << " increase 'batch_size' (default 1)" << std::endl; std::cout << " to submit several I/Os at once and report average rate" << std::endl; std::cout << " ops: write, reread and check (default); (R)ead only w/o verification;" << std::endl; std::cout << " read only with (V)erification; (W)rite only" << std::endl; std::cout << " length == 0 implies till end of space (please ignore the write error)" << std::endl; std::cout << " Memory consumption: block_size * batch_size * num_disks" << std::endl; exit(-1); } // returns throughput in MiB/s inline double throughput(double bytes, double seconds) { if (seconds == 0.0) return 0.0; return bytes / (1024 * 1024) / seconds; } int main(int argc, char * argv[]) { bool direct_io = true; bool sync_io = false; bool resize_after_open = false; const char * file_type = default_file_type; int arg_curr = 1; // FIXME: use something like getopt() instead of reinventing the wheel, // but there is some portability problem ... while (arg_curr < argc) { char * arg = argv[arg_curr]; char * arg_opt = strchr(argv[arg_curr], '='); if (arg_opt) { *arg_opt = 0; ++arg_opt; // skip '=' } if (strcmp(arg, "--no-direct") == 0) { direct_io = false; } else if (strcmp(arg, "--sync") == 0) { sync_io = true; } else if (strcmp(arg, "--file-type") == 0) { if (!arg_opt) { ++arg_curr; if (arg_curr < argc) arg_opt = argv[arg_curr]; else throw std::invalid_argument(std::string("missing argument for ") + arg); } file_type = arg_opt; } else if (strcmp(arg, "--resize") == 0) { resize_after_open = true; } else if (strncmp(arg, "--", 2) == 0) { throw std::invalid_argument(std::string("unknown option ") + arg); } else { // remaining arguments are "old style" command line break; } ++arg_curr; } if (argc < arg_curr + 3) usage(argv[0]); stxxl::int64 offset = stxxl::int64(GB) * stxxl::int64(atoi(argv[arg_curr])); stxxl::int64 length = stxxl::int64(GB) * stxxl::int64(atoi(argv[arg_curr + 1])); stxxl::int64 endpos = offset + length; stxxl::int64 block_size = 0; stxxl::int64 batch_size = 0; bool do_read = true, do_write = true, do_verify = true; int first_disk_arg = arg_curr + 2; if (first_disk_arg < argc) block_size = atoi(argv[first_disk_arg]); if (block_size > 0) { int l = strlen(argv[first_disk_arg]); if (argv[first_disk_arg][l - 1] == 'B' || argv[first_disk_arg][l - 1] == 'b') { // suffix B means exact size } else { block_size *= MB; } ++first_disk_arg; } else { block_size = 8 * MB; } if (first_disk_arg < argc) batch_size = atoi(argv[first_disk_arg]); if (batch_size > 0) { ++first_disk_arg; } else { batch_size = 1; } // deprecated, use --no-direct instead if (first_disk_arg < argc && (strcmp("nd", argv[first_disk_arg]) == 0 || strcmp("ND", argv[first_disk_arg]) == 0)) { direct_io = false; ++first_disk_arg; } if (first_disk_arg < argc && (strcmp("r", argv[first_disk_arg]) == 0 || strcmp("R", argv[first_disk_arg]) == 0)) { do_write = false; do_verify = false; ++first_disk_arg; } else if (first_disk_arg < argc && (strcmp("v", argv[first_disk_arg]) == 0 || strcmp("V", argv[first_disk_arg]) == 0)) { do_write = false; ++first_disk_arg; } else if (first_disk_arg < argc && (strcmp("w", argv[first_disk_arg]) == 0 || strcmp("W", argv[first_disk_arg]) == 0)) { do_read = false; ++first_disk_arg; } if (first_disk_arg < argc && strcmp("--", argv[first_disk_arg]) == 0) { ++first_disk_arg; } std::vector disks_arr; if (!(first_disk_arg < argc)) usage(argv[0]); const char * myrev = "$Revision: 2989 $"; const char * myself = strrchr(argv[0], '/'); if (!myself || !*(++myself)) myself = argv[0]; std::cout << "# " << myself << " " << myrev; #ifdef STXXL_DIRECT_IO_OFF std::cout << " STXXL_DIRECT_IO_OFF"; #endif std::cout << std::endl; std::cout << "# " << stxxl::get_version_string() << std::endl; for (int ii = first_disk_arg; ii < argc; ii++) { std::cout << "# Add disk: " << argv[ii] << std::endl; disks_arr.push_back(argv[ii]); } const unsigned ndisks = disks_arr.size(); const stxxl::unsigned_type step_size = block_size * batch_size; const unsigned block_size_int = block_size / sizeof(int); const stxxl::int64 step_size_int = step_size / sizeof(int); unsigned * buffer = (unsigned *)stxxl::aligned_alloc(step_size * ndisks); file ** disks = new file *[ndisks]; request_ptr * reqs = new request_ptr[ndisks * batch_size]; #ifdef WATCH_TIMES double * r_finish_times = new double[ndisks]; double * w_finish_times = new double[ndisks]; #endif double totaltimeread = 0, totaltimewrite = 0; stxxl::int64 totalsizeread = 0, totalsizewrite = 0; for (unsigned i = 0; i < ndisks * step_size_int; i++) buffer[i] = i; for (unsigned i = 0; i < ndisks; i++) { int openmode = file::CREAT | file::RDWR; if (direct_io) { #ifdef RAW_ACCESS openmode |= file::DIRECT; #endif } if (sync_io) { openmode |= file::SYNC; } disks[i] = stxxl::create_file(file_type, disks_arr[i], openmode, i); if (resize_after_open) disks[i]->set_size(endpos); } #ifdef DO_ONLY_READ do_write = false; #endif #ifdef NOREAD do_read = false; #endif std::cout << "# Step size: " << step_size << " bytes per disk (" << batch_size << " block" << (batch_size == 1 ? "" : "s") << " of " << block_size << " bytes)" << " file_type=" << file_type << " O_DIRECT=" << (direct_io ? "yes" : "no") << " O_SYNC=" << (sync_io ? "yes" : "no") << std::endl; timer t_total(true); try { while (offset + stxxl::int64(step_size) <= endpos || length == 0) { const stxxl::int64 current_step_size = (length == 0) ? stxxl::int64(step_size) : std::min(step_size, endpos - offset); const stxxl::int64 current_step_size_int = current_step_size / sizeof(int); const unsigned current_num_blocks = stxxl::div_ceil(current_step_size, block_size); std::cout << "Disk offset " << std::setw(8) << offset / MB << " MiB: " << std::fixed; double begin = timestamp(), end, elapsed; if (do_write) { for (unsigned i = 0; i < ndisks; i++) { for (unsigned j = 0; j < current_num_blocks; j++) reqs[i * current_num_blocks + j] = disks[i]->awrite(buffer + current_step_size_int * i + j * block_size_int, offset + j * block_size, block_size, stxxl::default_completion_handler()); } #ifdef WATCH_TIMES watch_times(reqs, ndisks, w_finish_times); #else wait_all(reqs, ndisks * current_num_blocks); #endif end = timestamp(); elapsed = end - begin; totalsizewrite += current_step_size; totaltimewrite += elapsed; } else { elapsed = 0.0; } #if 0 std::cout << "WRITE\nDisks: " << ndisks << " \nElapsed time: " << end - begin << " \nThroughput: " << int(double(current_step_size * ndisks) / MB / (end - begin)) << " MiB/s \nPer one disk:" << int(double(current_step_size) / MB / (end - begin)) << " MiB/s" << std::endl; #endif #ifdef WATCH_TIMES out_stat(begin, end, w_finish_times, ndisks, disks_arr); #endif std::cout << std::setw(2) << ndisks << " * " << std::setw(8) << std::setprecision(3) << (throughput(current_step_size, elapsed)) << " = " << std::setw(8) << std::setprecision(3) << (throughput(current_step_size, elapsed) * ndisks) << " MiB/s write,"; begin = timestamp(); if (do_read) { for (unsigned i = 0; i < ndisks; i++) { for (unsigned j = 0; j < current_num_blocks; j++) reqs[i * current_num_blocks + j] = disks[i]->aread(buffer + current_step_size_int * i + j * block_size_int, offset + j * block_size, block_size, stxxl::default_completion_handler()); } #ifdef WATCH_TIMES watch_times(reqs, ndisks, r_finish_times); #else wait_all(reqs, ndisks * current_num_blocks); #endif end = timestamp(); elapsed = end - begin; totalsizeread += current_step_size; totaltimeread += elapsed; } else { elapsed = 0.0; } #if 0 std::cout << "READ\nDisks: " << ndisks << " \nElapsed time: " << end - begin << " \nThroughput: " << int(double(current_step_size * ndisks) / MB / (end - begin)) << " MiB/s \nPer one disk:" << int(double(current_step_size) / MB / (end - begin)) << " MiB/s" << std::endl; #endif std::cout << std::setw(2) << ndisks << " * " << std::setw(8) << std::setprecision(3) << (throughput(current_step_size, elapsed)) << " = " << std::setw(8) << std::setprecision(3) << (throughput(current_step_size, elapsed) * ndisks) << " MiB/s read"; #ifdef WATCH_TIMES out_stat(begin, end, r_finish_times, ndisks, disks_arr); #endif if (do_read && do_verify) { for (unsigned i = 0; i < ndisks * current_step_size_int; i++) { if (buffer[i] != i) { int ibuf = i / current_step_size_int; int pos = i % current_step_size_int; std::cout << "Error on disk " << ibuf << " position " << std::hex << std::setw(8) << offset + pos * sizeof(int) << " got: " << std::hex << std::setw(8) << buffer[i] << " wanted: " << std::hex << std::setw(8) << i << std::dec << std::endl; i = (ibuf + 1) * current_step_size_int; // jump to next } } } std::cout << std::endl; offset += current_step_size; } } catch (const std::exception & ex) { std::cout << std::endl; STXXL_ERRMSG(ex.what()); } t_total.stop(); std::cout << "=============================================================================================" << std::endl; // the following line of output is parsed by misc/diskbench-avgplot.sh std::cout << "# Average over " << std::setw(8) << stxxl::STXXL_MAX(totalsizewrite, totalsizeread) / MB << " MiB: "; std::cout << std::setw(2) << ndisks << " * " << std::setw(8) << std::setprecision(3) << (throughput(totalsizewrite, totaltimewrite)) << " = " << std::setw(8) << std::setprecision(3) << (throughput(totalsizewrite, totaltimewrite) * ndisks) << " MiB/s write,"; std::cout << std::setw(2) << ndisks << " * " << std::setw(8) << std::setprecision(3) << (throughput(totalsizeread, totaltimeread)) << " = " << std::setw(8) << std::setprecision(3) << (throughput(totalsizeread, totaltimeread) * ndisks) << " MiB/s read" << std::endl; if (totaltimewrite != 0.0) std::cout << "# Write time " << std::setw(8) << std::setprecision(3) << totaltimewrite << " s" << std::endl; if (totaltimeread != 0.0) std::cout << "# Read time " << std::setw(8) << std::setprecision(3) << totaltimeread << " s" << std::endl; std::cout << "# Non-I/O time " << std::setw(8) << std::setprecision(3) << (t_total.seconds() - totaltimewrite - totaltimeread) << " s, average throughput " << std::setw(8) << std::setprecision(3) << (throughput(totalsizewrite + totalsizeread, t_total.seconds() - totaltimewrite - totaltimeread) * ndisks) << " MiB/s" << std::endl; std::cout << "# Total time " << std::setw(8) << std::setprecision(3) << t_total.seconds() << " s, average throughput " << std::setw(8) << std::setprecision(3) << (throughput(totalsizewrite + totalsizeread, t_total.seconds()) * ndisks) << " MiB/s" << std::endl; #ifdef WATCH_TIMES delete[] r_finish_times; delete[] w_finish_times; #endif delete[] reqs; for (unsigned i = 0; i < ndisks; i++) delete disks[i]; delete[] disks; stxxl::aligned_dealloc(buffer); return 0; } // vim: et:ts=4:sw=4 stxxl-1.3.1/io/wincall_file.cpp0000644000175000017500000000775011535550674016301 0ustar andreasandreas/*************************************************************************** * io/wincall_file.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2005-2006 Roman Dementiev * Copyright (C) 2008-2010 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #include #if STXXL_HAVE_WINCALL_FILE #include #include #include __STXXL_BEGIN_NAMESPACE void wincall_file::serve(const request * req) throw (io_error) { scoped_mutex_lock fd_lock(fd_mutex); assert(req->get_file() == this); offset_type offset = req->get_offset(); void * buffer = req->get_buffer(); size_type bytes = req->get_size(); request::request_type type = req->get_type(); if (bytes > 32 * 1024 * 1024) { STXXL_ERRMSG("Using a block size larger than 32 MiB may not work with the " << io_type() << " filetype"); } HANDLE handle = file_des; LARGE_INTEGER desired_pos; desired_pos.QuadPart = offset; if (!SetFilePointerEx(handle, desired_pos, NULL, FILE_BEGIN)) { stxxl_win_lasterror_exit("SetFilePointerEx in wincall_request::serve()" << " offset=" << offset << " this=" << this << " buffer=" << buffer << " bytes=" << bytes << " type=" << ((type == request::READ) ? "READ" : "WRITE"), io_error); } else { stats::scoped_read_write_timer read_write_timer(bytes, type == request::WRITE); if (type == request::READ) { DWORD NumberOfBytesRead = 0; if (!ReadFile(handle, buffer, bytes, &NumberOfBytesRead, NULL)) { stxxl_win_lasterror_exit("ReadFile" << " this=" << this << " offset=" << offset << " buffer=" << buffer << " bytes=" << bytes << " type=" << ((type == request::READ) ? "READ" : "WRITE") << " NumberOfBytesRead= " << NumberOfBytesRead, io_error); } else if (NumberOfBytesRead != bytes) { stxxl_win_lasterror_exit(" partial read: missing " << (bytes - NumberOfBytesRead) << " out of " << bytes << " bytes", io_error); } } else { DWORD NumberOfBytesWritten = 0; if (!WriteFile(handle, buffer, bytes, &NumberOfBytesWritten, NULL)) { stxxl_win_lasterror_exit("WriteFile" << " this=" << this << " offset=" << offset << " buffer=" << buffer << " bytes=" << bytes << " type=" << ((type == request::READ) ? "READ" : "WRITE") << " NumberOfBytesWritten= " << NumberOfBytesWritten, io_error); } else if (NumberOfBytesWritten != bytes) { stxxl_win_lasterror_exit(" partial write: missing " << (bytes - NumberOfBytesWritten) << " out of " << bytes << " bytes", io_error); } } } } const char * wincall_file::io_type() const { return "wincall"; } __STXXL_END_NAMESPACE #endif // #if STXXL_HAVE_WINCALL_FILE // vim: et:ts=4:sw=4 stxxl-1.3.1/io/request.cpp0000644000175000017500000000566311535637727015347 0ustar andreasandreas/*************************************************************************** * io/request.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2008 Andreas Beckmann * Copyright (C) 2009 Johannes Singler * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #include #include #include __STXXL_BEGIN_NAMESPACE request::request(const completion_handler & on_compl, file * file__, void * buffer_, offset_type offset_, size_type bytes_, request_type type_) : on_complete(on_compl), ref_cnt(0), file_(file__), buffer(buffer_), offset(offset_), bytes(bytes_), type(type_) { STXXL_VERBOSE3("[" << static_cast(this) << "] request::(...), ref_cnt=" << ref_cnt); file_->add_request_ref(); } request::~request() { STXXL_VERBOSE3("[" << static_cast(this) << "] request::~(), ref_cnt=" << ref_cnt); } void request::completed() { on_complete(this); notify_waiters(); file_->delete_request_ref(); file_ = 0; } void request::check_alignment() const { if (offset % BLOCK_ALIGN != 0) STXXL_ERRMSG("Offset is not aligned: modulo " << BLOCK_ALIGN << " = " << offset % BLOCK_ALIGN); if (bytes % BLOCK_ALIGN != 0) STXXL_ERRMSG("Size is not a multiple of " << BLOCK_ALIGN << ", = " << bytes % BLOCK_ALIGN); if (unsigned_type(buffer) % BLOCK_ALIGN != 0) STXXL_ERRMSG("Buffer is not aligned: modulo " << BLOCK_ALIGN << " = " << unsigned_type(buffer) % BLOCK_ALIGN << " (" << buffer << ")"); } void request::check_nref_failed(bool after) { STXXL_ERRMSG("WARNING: serious error, reference to the request is lost " << (after ? "after " : "before") << " serve" << " nref=" << nref() << " this=" << this << " offset=" << offset << " buffer=" << buffer << " bytes=" << bytes << " type=" << ((type == READ) ? "READ" : "WRITE") << " file=" << get_file() << " iotype=" << get_file()->io_type() ); } std::ostream & request::print(std::ostream & out) const { out << "File object address: " << static_cast(get_file()); out << " Buffer address: " << static_cast(get_buffer()); out << " File offset: " << get_offset(); out << " Transfer size: " << get_size() << " bytes"; out << " Type of transfer: " << ((get_type() == READ) ? "READ" : "WRITE"); return out; } __STXXL_END_NAMESPACE // vim: et:ts=4:sw=4 stxxl-1.3.1/io/Makefile0000644000175000017500000001431511535563072014574 0ustar andreasandreasinclude Makefile.common include ../make.settings tools: $(UTIL_BINARIES) tests: $(TESTS) #tests: $(TESTS_NON_MSVC) lib: ufs_file_base.$(OBJEXT) syscall_file.$(OBJEXT) wincall_file.$(OBJEXT) wfs_file_base.$(OBJEXT) \ iostats.$(OBJEXT) \ mmap_file.$(OBJEXT) simdisk_file.$(OBJEXT) boostfd_file.$(OBJEXT) mem_file.$(OBJEXT) \ fileperblock_file.$(OBJEXT) request.$(OBJEXT) request_with_waiters.$(OBJEXT) \ request_with_state.$(OBJEXT) serving_request.$(OBJEXT) \ disk_queued_file.$(OBJEXT) request_queue_impl_qwqr.$(OBJEXT) request_queue_impl_1q.$(OBJEXT) \ request_queue_impl_worker.$(OBJEXT) wbtl_file.$(OBJEXT) create_file.$(OBJEXT) ufs_file_base.$(OBJEXT): ufs_file_base.cpp $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c ufs_file_base.cpp syscall_file.$(OBJEXT): syscall_file.cpp $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c syscall_file.cpp wbtl_file.$(OBJEXT): wbtl_file.cpp $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c wbtl_file.cpp wincall_file.$(OBJEXT): wincall_file.cpp $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c wincall_file.cpp wfs_file_base.$(OBJEXT): wfs_file_base.cpp $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c wfs_file_base.cpp iostats.$(OBJEXT): iostats.cpp $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c iostats.cpp mmap_file.$(OBJEXT): mmap_file.cpp $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c mmap_file.cpp simdisk_file.$(OBJEXT): simdisk_file.cpp $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c simdisk_file.cpp boostfd_file.$(OBJEXT): boostfd_file.cpp $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c boostfd_file.cpp mem_file.$(OBJEXT): mem_file.cpp $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c mem_file.cpp fileperblock_file.$(OBJEXT): fileperblock_file.cpp $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c fileperblock_file.cpp request.$(OBJEXT): request.cpp $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c request.cpp request_with_state.$(OBJEXT): request_with_state.cpp $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c request_with_state.cpp request_with_waiters.$(OBJEXT): request_with_waiters.cpp $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c request_with_waiters.cpp serving_request.$(OBJEXT): serving_request.cpp $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c serving_request.cpp disk_queued_file.$(OBJEXT): disk_queued_file.cpp $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c disk_queued_file.cpp request_queue_impl_qwqr.$(OBJEXT): request_queue_impl_qwqr.cpp $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c request_queue_impl_qwqr.cpp request_queue_impl_1q.$(OBJEXT): request_queue_impl_1q.cpp $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c request_queue_impl_1q.cpp request_queue_impl_worker.$(OBJEXT): request_queue_impl_worker.cpp $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c request_queue_impl_worker.cpp create_file.$(OBJEXT): create_file.cpp $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c create_file.cpp DEPENDENCIES = $(COMMON_FILES) $(IO_LAYER_FILES) test_io: test_io.$(EXEEXT) test_io.$(EXEEXT): test_io.cpp $(DEPENDENCIES) $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c test_io.cpp $(LINKER) test_io.$(OBJEXT) $(OUT)test_io.$(EXEEXT) $(STXXL_LINKER_OPTIONS) test_io_sizes: test_io_sizes.$(EXEEXT) test_io_sizes.$(EXEEXT): test_io_sizes.cpp $(DEPENDENCIES) $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c test_io_sizes.cpp $(LINKER) test_io_sizes.$(OBJEXT) $(OUT)test_io_sizes.$(EXEEXT) $(STXXL_LINKER_OPTIONS) test_cancel: test_cancel.$(EXEEXT) test_cancel.$(EXEEXT): test_cancel.cpp $(DEPENDENCIES) $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c test_cancel.cpp $(LINKER) test_cancel.$(OBJEXT) $(OUT)test_cancel.$(EXEEXT) $(STXXL_LINKER_OPTIONS) benchmark_disks: benchmark_disks.$(EXEEXT) benchmark_disks.$(EXEEXT): benchmark_disks.cpp $(DEPENDENCIES) $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c benchmark_disks.cpp $(LINKER) benchmark_disks.$(OBJEXT) $(OUT)benchmark_disks.$(EXEEXT) $(STXXL_LINKER_OPTIONS) flushbuffers: flushbuffers.$(EXEEXT) flushbuffers.$(EXEEXT): flushbuffers.cpp $(DEPENDENCIES) $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c flushbuffers.cpp $(LINKER) flushbuffers.$(OBJEXT) $(OUT)flushbuffers.$(EXEEXT) $(STXXL_LINKER_OPTIONS) unittest: unittest.$(EXEEXT) unittest.$(EXEEXT): unittest.cpp $(COMPILER) $(STXXL_COMPILER_OPTIONS) $(CPPUNIT_COMPILER_OPTIONS) -c unittest.cpp $(LINKER) unittest.$(OBJEXT) $(OUT)unittest.$(EXEEXT) $(STXXL_LINKER_OPTIONS) $(CPPUNIT_LINKER_OPTIONS) sd_test: sd_test.$(EXEEXT) sd_test.$(EXEEXT): sd_test.cpp $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c sd_test.cpp $(LINKER) sd_test.$(OBJEXT) $(OUT)sd_test.$(EXEEXT) $(STXXL_LINKER_OPTIONS) $(CPPUNIT_LINKER_OPTIONS) gen_file: gen_file.$(EXEEXT) gen_file.$(EXEEXT): gen_file.cpp $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c gen_file.cpp $(LINKER) gen_file.$(OBJEXT) $(OUT)gen_file.$(EXEEXT) $(STXXL_LINKER_OPTIONS) $(CPPUNIT_LINKER_OPTIONS) benchmark_disk_and_flash: benchmark_disk_and_flash.$(EXEEXT) benchmark_disk_and_flash.$(EXEEXT): benchmark_disk_and_flash.cpp $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c benchmark_disk_and_flash.cpp $(LINKER) benchmark_disk_and_flash.$(OBJEXT) $(OUT)benchmark_disk_and_flash.$(EXEEXT) $(STXXL_LINKER_OPTIONS) $(CPPUNIT_LINKER_OPTIONS) benchmark_configured_disks: benchmark_configured_disks.$(EXEEXT) benchmark_configured_disks.$(EXEEXT): benchmark_configured_disks.cpp $(DEPENDENCIES) $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c benchmark_configured_disks.cpp $(LINKER) benchmark_configured_disks.$(OBJEXT) $(OUT)benchmark_configured_disks.$(EXEEXT) $(STXXL_LINKER_OPTIONS) benchmark_random_block_access: benchmark_random_block_access.$(EXEEXT) benchmark_random_block_access.$(EXEEXT): benchmark_random_block_access.cpp $(DEPENDENCIES) $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c benchmark_random_block_access.cpp $(LINKER) benchmark_random_block_access.$(OBJEXT) $(OUT)benchmark_random_block_access.$(EXEEXT) $(STXXL_LINKER_OPTIONS) iobench_scatter_in_place: iobench_scatter_in_place.$(EXEEXT) iobench_scatter_in_place.$(EXEEXT): iobench_scatter_in_place.cpp $(DEPENDENCIES) $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c iobench_scatter_in_place.cpp $(LINKER) iobench_scatter_in_place.$(OBJEXT) $(OUT)iobench_scatter_in_place.$(EXEEXT) $(STXXL_LINKER_OPTIONS) verify_disks: verify_disks.$(EXEEXT) verify_disks.$(EXEEXT): verify_disks.cpp $(DEPENDENCIES) $(COMPILER) $(STXXL_COMPILER_OPTIONS) -c verify_disks.cpp $(LINKER) verify_disks.$(OBJEXT) $(OUT)verify_disks.$(EXEEXT) $(STXXL_LINKER_OPTIONS) clean: $(RM) $(CLEAN_TARGETS) stxxl-1.3.1/io/verify_disks.cpp0000644000175000017500000003651011427751122016335 0ustar andreasandreas/*************************************************************************** * io/verify_disks.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2002-2003 Roman Dementiev * Copyright (C) 2007-2010 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ /* example gnuplot command for the output of this program: (x-axis: disk offset in GiB, y-axis: bandwidth in MiB/s) plot \ "disk.log" using ($3/1024):($14) w l title "read", \ "disk.log" using ($3/1024):($7) w l title "write" */ #include #include #include #include #include using stxxl::request_ptr; using stxxl::file; using stxxl::timer; using stxxl::timestamp; #ifdef BLOCK_ALIGN #undef BLOCK_ALIGN #endif #define BLOCK_ALIGN 4096 //#define NOREAD //#define DO_ONLY_READ #define POLL_DELAY 1000 #define RAW_ACCESS //#define WATCH_TIMES #ifdef WATCH_TIMES void watch_times(request_ptr reqs[], unsigned n, double * out) { bool * finished = new bool[n]; unsigned count = 0; for (unsigned i = 0; i < n; i++) finished[i] = false; while (count != n) { usleep(POLL_DELAY); unsigned i = 0; for (i = 0; i < n; i++) { if (!finished[i]) if (reqs[i]->poll()) { finished[i] = true; out[i] = timestamp(); count++; } } } delete[] finished; } void out_stat(double start, double end, double * times, unsigned n, const std::vector & names) { for (unsigned i = 0; i < n; i++) { std::cout << i << " " << names[i] << " took " << 100. * (times[i] - start) / (end - start) << " %" << std::endl; } } #endif #define MB (1024 * 1024) #define GB (1024 * 1024 * 1024) void usage(const char * argv0) { std::cout << "Usage: " << argv0 << " pattern offset length [block_size [batch_size]] [nd] [r|w] [--] diskfile..." << std::endl; std::cout << " 'pattern' is a 32bit unsigned value like '0', '0xffffffff', ..." << std::endl; std::cout << " starting 'offset' and 'length' are given in GiB," << std::endl; std::cout << " 'block_size' (default 8) in MiB (in B if it has a suffix B)," << std::endl; std::cout << " increase 'batch_size' (default 1)" << std::endl; std::cout << " to submit several I/Os at once and report average rate" << std::endl; #ifdef RAW_ACCESS std::cout << " open mode: includes O_DIRECT unless the 'nd' flag is given" << std::endl; #endif std::cout << " ops: write and reread (default), (r)ead only, (w)rite only" << std::endl; std::cout << " length == 0 implies till end of space (please ignore the write error)" << std::endl; std::cout << " Memory consumption: block_size * batch_size * num_disks" << std::endl; exit(-1); } // returns throughput in MiB/s inline double throughput(double bytes, double seconds) { if (seconds == 0.0) return 0.0; return bytes / (1024 * 1024) / seconds; } int main(int argc, char * argv[]) { if (argc < 5) usage(argv[0]); unsigned pattern = strtol(argv[1], NULL, 0); stxxl::int64 offset = stxxl::int64(GB) * stxxl::int64(atoi(argv[2])); stxxl::int64 length = stxxl::int64(GB) * stxxl::int64(atoi(argv[3])); stxxl::int64 endpos = offset + length; stxxl::int64 block_size = 0; stxxl::int64 batch_size = 0; bool verify_failed = false; bool do_read = true, do_write = true; bool direct_io = true; int first_disk_arg = 4; if (first_disk_arg < argc) block_size = atoi(argv[first_disk_arg]); if (block_size > 0) { int l = strlen(argv[first_disk_arg]); if (argv[first_disk_arg][l - 1] == 'B' || argv[first_disk_arg][l - 1] == 'b') { // suffix B means exact size } else { block_size *= MB; } ++first_disk_arg; } else { block_size = 8 * MB; } if (first_disk_arg < argc) batch_size = atoi(argv[first_disk_arg]); if (batch_size > 0) { ++first_disk_arg; } else { batch_size = 1; } if (first_disk_arg < argc && (strcmp("nd", argv[first_disk_arg]) == 0 || strcmp("ND", argv[first_disk_arg]) == 0)) { direct_io = false; ++first_disk_arg; } if (first_disk_arg < argc && (strcmp("r", argv[first_disk_arg]) == 0 || strcmp("R", argv[first_disk_arg]) == 0)) { do_write = false; ++first_disk_arg; } else if (first_disk_arg < argc && (strcmp("w", argv[first_disk_arg]) == 0 || strcmp("W", argv[first_disk_arg]) == 0)) { do_read = false; ++first_disk_arg; } if (first_disk_arg < argc && strcmp("--", argv[first_disk_arg]) == 0) { ++first_disk_arg; } std::vector disks_arr; if (!(first_disk_arg < argc)) usage(argv[0]); for (int ii = first_disk_arg; ii < argc; ii++) { std::cout << "# Add disk: " << argv[ii] << std::endl; disks_arr.push_back(argv[ii]); } const unsigned ndisks = disks_arr.size(); const stxxl::unsigned_type step_size = block_size * batch_size; const unsigned block_size_int = block_size / sizeof(int); const stxxl::int64 step_size_int = step_size / sizeof(int); unsigned * buffer = (unsigned *)stxxl::aligned_alloc(step_size * ndisks); file ** disks = new file *[ndisks]; request_ptr * reqs = new request_ptr[ndisks * batch_size]; #ifdef WATCH_TIMES double * r_finish_times = new double[ndisks]; double * w_finish_times = new double[ndisks]; #endif double totaltimeread = 0, totaltimewrite = 0; stxxl::int64 totalsizeread = 0, totalsizewrite = 0; for (unsigned i = 0; i < ndisks * step_size_int; i++) buffer[i] = pattern; for (unsigned i = 0; i < ndisks; i++) { int openmode = file::CREAT | file::RDWR; if (direct_io) { #ifdef RAW_ACCESS openmode |= file::DIRECT; #endif } #ifdef BOOST_MSVC disks[i] = new stxxl::wincall_file(disks_arr[i], openmode, i); #else disks[i] = new stxxl::syscall_file(disks_arr[i], openmode, i); #endif } #ifdef DO_ONLY_READ do_write = false; #endif #ifdef NOREAD do_read = false; #endif const char * myrev = "$Revision: 2528 $"; const char * myself = strrchr(argv[0], '/'); if (!myself || !*(++myself)) myself = argv[0]; std::cout << "# " << myself << " " << myrev << std::endl; std::cout << "# Step size: " << step_size << " bytes per disk (" << batch_size << " block" << (batch_size == 1 ? "" : "s") << " of " << block_size << " bytes) pattern=0x" << std::hex << pattern << std::dec << std::endl; timer t_total(true); try { while (offset < endpos) { const stxxl::int64 current_step_size = std::min(step_size, endpos - offset); const stxxl::int64 current_step_size_int = current_step_size / sizeof(int); const unsigned current_num_blocks = stxxl::div_ceil(current_step_size, block_size); std::cout << "Disk offset " << std::setw(8) << offset / MB << " MiB: " << std::fixed; double begin = timestamp(), end, elapsed; if (do_write) { // write block number (512 byte blocks) into each block at position 42 * sizeof(unsigned) for (unsigned j = 42, b = offset >> 9; j < current_step_size_int; j += 512 / sizeof(unsigned), ++b) { for (unsigned i = 0; i < ndisks; i++) buffer[current_step_size_int * i + j] = b; } for (unsigned i = 0; i < ndisks; i++) { for (unsigned j = 0; j < current_num_blocks; j++) reqs[i * current_num_blocks + j] = disks[i]->awrite(buffer + current_step_size_int * i + j * block_size_int, offset + j * block_size, block_size, stxxl::default_completion_handler()); } #ifdef WATCH_TIMES watch_times(reqs, ndisks, w_finish_times); #else wait_all(reqs, ndisks * current_num_blocks); #endif end = timestamp(); elapsed = end - begin; totalsizewrite += current_step_size; totaltimewrite += elapsed; } else { elapsed = 0.0; } #if 0 std::cout << "WRITE\nDisks: " << ndisks << " \nElapsed time: " << end - begin << " \nThroughput: " << int(double(current_step_size * ndisks) / MB / (end - begin)) << " MiB/s \nPer one disk:" << int(double(current_step_size) / MB / (end - begin)) << " MiB/s" << std::endl; #endif #ifdef WATCH_TIMES out_stat(begin, end, w_finish_times, ndisks, disks_arr); #endif std::cout << std::setw(2) << ndisks << " * " << std::setw(8) << std::setprecision(3) << (throughput(current_step_size, elapsed)) << " = " << std::setw(8) << std::setprecision(3) << (throughput(current_step_size, elapsed) * ndisks) << " MiB/s write,"; begin = timestamp(); if (do_read) { for (unsigned i = 0; i < ndisks; i++) { for (unsigned j = 0; j < current_num_blocks; j++) reqs[i * current_num_blocks + j] = disks[i]->aread(buffer + current_step_size_int * i + j * block_size_int, offset + j * block_size, block_size, stxxl::default_completion_handler()); } #ifdef WATCH_TIMES watch_times(reqs, ndisks, r_finish_times); #else wait_all(reqs, ndisks * current_num_blocks); #endif end = timestamp(); elapsed = end - begin; totalsizeread += current_step_size; totaltimeread += elapsed; } else { elapsed = 0.0; } #if 0 std::cout << "READ\nDisks: " << ndisks << " \nElapsed time: " << end - begin << " \nThroughput: " << int(double(current_step_size * ndisks) / MB / (end - begin)) << " MiB/s \nPer one disk:" << int(double(current_step_size) / MB / (end - begin)) << " MiB/s" << std::endl; #endif std::cout << std::setw(2) << ndisks << " * " << std::setw(8) << std::setprecision(3) << (throughput(current_step_size, elapsed)) << " = " << std::setw(8) << std::setprecision(3) << (throughput(current_step_size, elapsed) * ndisks) << " MiB/s read"; #ifdef WATCH_TIMES out_stat(begin, end, r_finish_times, ndisks, disks_arr); #endif if (do_read) { for (unsigned d = 0; d < ndisks; ++d) { for (unsigned s = 0; s < (current_step_size >> 9); ++s) { unsigned i = d * current_step_size_int + s * (512 / sizeof(unsigned)) + 42; unsigned b = (offset >> 9) + s; if (buffer[i] != b) { verify_failed = true; std::cout << "Error on disk " << d << " sector " << std::hex << std::setw(8) << b << " got: " << std::hex << std::setw(8) << buffer[i] << " wanted: " << std::hex << std::setw(8) << b << std::dec << std::endl; } buffer[i] = pattern; } } for (unsigned i = 0; i < ndisks * current_step_size_int; i++) { if (buffer[i] != pattern) { verify_failed = true; int ibuf = i / current_step_size_int; int pos = i % current_step_size_int; std::cout << "Error on disk " << ibuf << " position " << std::hex << std::setw(8) << offset + pos * sizeof(int) << " got: " << std::hex << std::setw(8) << buffer[i] << " wanted: " << std::hex << std::setw(8) << pattern << std::dec << std::endl; i = (ibuf + 1) * current_step_size_int; // jump to next } } } std::cout << std::endl; offset += current_step_size; } } catch (const std::exception & ex) { std::cout << std::endl; STXXL_ERRMSG(ex.what()); } t_total.stop(); std::cout << "=============================================================================================" << std::endl; // the following line of output is parsed by misc/diskbench-avgplot.sh std::cout << "# Average over " << std::setw(8) << stxxl::STXXL_MAX(totalsizewrite, totalsizeread) / MB << " MiB: "; std::cout << std::setw(2) << ndisks << " * " << std::setw(8) << std::setprecision(3) << (throughput(totalsizewrite, totaltimewrite)) << " = " << std::setw(8) << std::setprecision(3) << (throughput(totalsizewrite, totaltimewrite) * ndisks) << " MiB/s write,"; std::cout << std::setw(2) << ndisks << " * " << std::setw(8) << std::setprecision(3) << (throughput(totalsizeread, totaltimeread)) << " = " << std::setw(8) << std::setprecision(3) << (throughput(totalsizeread, totaltimeread) * ndisks) << " MiB/s read" << std::endl; if (totaltimewrite != 0.0) std::cout << "# Write time " << std::setw(8) << std::setprecision(3) << totaltimewrite << " s" << std::endl; if (totaltimeread != 0.0) std::cout << "# Read time " << std::setw(8) << std::setprecision(3) << totaltimeread << " s" << std::endl; std::cout << "# Non-I/O time " << std::setw(8) << std::setprecision(3) << (t_total.seconds() - totaltimewrite - totaltimeread) << " s, average throughput " << std::setw(8) << std::setprecision(3) << (throughput(totalsizewrite + totalsizeread, t_total.seconds() - totaltimewrite - totaltimeread) * ndisks) << " MiB/s" << std::endl; std::cout << "# Total time " << std::setw(8) << std::setprecision(3) << t_total.seconds() << " s, average throughput " << std::setw(8) << std::setprecision(3) << (throughput(totalsizewrite + totalsizeread, t_total.seconds()) * ndisks) << " MiB/s" << std::endl; #ifdef WATCH_TIMES delete[] r_finish_times; delete[] w_finish_times; #endif delete[] reqs; for (unsigned i = 0; i < ndisks; i++) delete disks[i]; delete[] disks; stxxl::aligned_dealloc(buffer); return verify_failed ? 1 : 0; } // vim: et:ts=4:sw=4 stxxl-1.3.1/io/create_file.cpp0000644000175000017500000000730711535723350016102 0ustar andreasandreas/*************************************************************************** * io/create_file.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2002 Roman Dementiev * Copyright (C) 2008, 2010 Andreas Beckmann * Copyright (C) 2008, 2009 Johannes Singler * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #include #include __STXXL_BEGIN_NAMESPACE file * create_file(const std::string & io_impl, const std::string & filename, int options, int physical_device_id, int allocator_id) { if (io_impl == "syscall") { ufs_file_base * result = new syscall_file(filename, options, physical_device_id, allocator_id); result->lock(); return result; } else if (io_impl == "fileperblock_syscall") { fileperblock_file * result = new fileperblock_file(filename, options, physical_device_id, allocator_id); result->lock(); return result; } #if STXXL_HAVE_MMAP_FILE else if (io_impl == "mmap") { ufs_file_base * result = new mmap_file(filename, options, physical_device_id, allocator_id); result->lock(); return result; } else if (io_impl == "fileperblock_mmap") { fileperblock_file * result = new fileperblock_file(filename, options, physical_device_id, allocator_id); result->lock(); return result; } #endif #if STXXL_HAVE_SIMDISK_FILE else if (io_impl == "simdisk") { options &= ~stxxl::file::DIRECT; // clear the DIRECT flag, this file is supposed to be on tmpfs ufs_file_base * result = new sim_disk_file(filename, options, physical_device_id, allocator_id); result->lock(); return result; } #endif #if STXXL_HAVE_WINCALL_FILE else if (io_impl == "wincall") { wfs_file_base * result = new wincall_file(filename, options, physical_device_id, allocator_id); result->lock(); return result; } else if (io_impl == "fileperblock_wincall") { fileperblock_file * result = new fileperblock_file(filename, options, physical_device_id, allocator_id); result->lock(); return result; } #endif #if STXXL_HAVE_BOOSTFD_FILE else if (io_impl == "boostfd") { boostfd_file * result = new boostfd_file(filename, options, physical_device_id, allocator_id); result->lock(); return result; } else if (io_impl == "fileperblock_boostfd") { fileperblock_file * result = new fileperblock_file(filename, options, physical_device_id, allocator_id); result->lock(); return result; } #endif else if (io_impl == "memory") { mem_file * result = new mem_file(physical_device_id, allocator_id); result->lock(); return result; } #if STXXL_HAVE_WBTL_FILE else if (io_impl == "wbtl") { ufs_file_base * backend = new syscall_file(filename, options, -1, -1); // FIXME: ID wbtl_file * result = new stxxl::wbtl_file(backend, 16 * 1024 * 1024, 2, physical_device_id, allocator_id); result->lock(); return result; } #endif STXXL_THROW(std::runtime_error, "FileCreator::create", "Unsupported disk I/O implementation " << io_impl << " ."); return NULL; } __STXXL_END_NAMESPACE // vim: et:ts=4:sw=4 stxxl-1.3.1/io/simdisk_file.cpp0000644000175000017500000001644411535571065016310 0ustar andreasandreas/*************************************************************************** * io/simdisk_file.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2002-2003 Roman Dementiev * Copyright (C) 2008 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #include #if STXXL_HAVE_SIMDISK_FILE #include #include __STXXL_BEGIN_NAMESPACE void DiskGeometry::add_zone(int & first_cyl, int last_cyl, int sec_per_track, int & first_sect) { double rate = nsurfaces * sec_per_track * bytes_per_sector / ((nsurfaces - 1) * head_switch_time + cyl_switch_time + nsurfaces * revolution_time); int sectors = (last_cyl - first_cyl + 1) * nsurfaces * sec_per_track; zones.insert(Zone(first_sect, sectors, rate)); first_sect += sectors; first_cyl = last_cyl + 1; } // returns delay in s double DiskGeometry::get_delay(file::offset_type offset, file::size_type size) { #if 0 int first_sect = offset / bytes_per_sector; int last_sect = (offset + size) / bytes_per_sector; int sectors = size / bytes_per_sector; double delay = cmd_ovh + seek_time + rot_latency + double(bytes_per_sector) / double(interface_speed); std::set::iterator zone = zones.lower_bound(first_sect); //std::cout << __PRETTY_FUNCTION__ << " " << (*zone).first_sector << std::endl; while (1) { int from_this_zone = last_sect - ((*zone).first_sector + (*zone).sectors); if (from_this_zone <= 0) { delay += sectors * bytes_per_sector / ((*zone).sustained_data_rate); break; } else { delay += from_this_zone * bytes_per_sector / ((*zone).sustained_data_rate); zone++; stxxl_nassert(zone == zones.end()); sectors -= from_this_zone; } } return delay; #else STXXL_UNUSED(offset); return double(size) / double(AVERAGE_SPEED); #endif } IC35L080AVVA07::IC35L080AVVA07() { std::cout << "Creating IBM 120GXP IC35L080AVVA07" << std::endl; nsurfaces = 4; bytes_per_sector = 512; cmd_ovh = 0.0002; // in s seek_time = 0.0082; // in s rot_latency = 0.00417; // in s head_switch_time = 0.0015; // in s cyl_switch_time = 0.002; // in s revolution_time = 0.0083; // in s interface_speed = 100000000; // in byte/s int first_sect = 0; int last_cyl = 0; add_zone(last_cyl, 1938, 928, first_sect); add_zone(last_cyl, 3756, 921, first_sect); add_zone(last_cyl, 5564, 896, first_sect); add_zone(last_cyl, 7687, 896, first_sect); add_zone(last_cyl, 9526, 888, first_sect); add_zone(last_cyl, 11334, 883, first_sect); add_zone(last_cyl, 13331, 864, first_sect); add_zone(last_cyl, 15128, 850, first_sect); add_zone(last_cyl, 16925, 840, first_sect); add_zone(last_cyl, 18922, 822, first_sect); add_zone(last_cyl, 20709, 806, first_sect); add_zone(last_cyl, 22601, 792, first_sect); add_zone(last_cyl, 24138, 787, first_sect); add_zone(last_cyl, 26024, 768, first_sect); add_zone(last_cyl, 27652, 752, first_sect); add_zone(last_cyl, 29501, 740, first_sect); add_zone(last_cyl, 31234, 725, first_sect); add_zone(last_cyl, 33009, 698, first_sect); add_zone(last_cyl, 34784, 691, first_sect); add_zone(last_cyl, 36609, 672, first_sect); add_zone(last_cyl, 38374, 648, first_sect); add_zone(last_cyl, 40139, 630, first_sect); add_zone(last_cyl, 41904, 614, first_sect); add_zone(last_cyl, 43519, 595, first_sect); add_zone(last_cyl, 45250, 576, first_sect); add_zone(last_cyl, 47004, 552, first_sect); add_zone(last_cyl, 48758, 533, first_sect); add_zone(last_cyl, 50491, 512, first_sect); add_zone(last_cyl, 52256, 493, first_sect); add_zone(last_cyl, 54010, 471, first_sect); add_zone(last_cyl, 55571, 448, first_sect); #if 0 set::iterator it = zones.begin(); int i = 0; for ( ; it != zones.end(); it++, i++) { //const int block_size = 128*3*1024* 4; // one cylinder std::cout << "Zone " << i << " first sector: " << (*it).first_sector; std::cout << " sectors: " << (*it).sectors << " sustained rate: "; std::cout << (*it).sustained_data_rate / 1024 / 1024 << " MiB/s" << std::endl; } std::cout << "Last sector : " << first_sect << std::endl; std::cout << "Approx. capacity: " << (first_sect / 1024 / 1024) * bytes_per_sector << " MiB" << std::endl; #endif std::cout << "Transfer 16 MiB from zone 0 : " << get_delay(0, 16 * 1024 * 1024) << " s" << std::endl; std::cout << "Transfer 16 MiB from zone 30: " << get_delay(file::offset_type(158204036) * file::offset_type(bytes_per_sector), 16 * 1024 * 1024) << " s" << std::endl; } //////////////////////////////////////////////////////////////////////////// void sim_disk_file::serve(const request * req) throw (io_error) { scoped_mutex_lock fd_lock(fd_mutex); assert(req->get_file() == this); offset_type offset = req->get_offset(); void * buffer = req->get_buffer(); size_type bytes = req->get_size(); request::request_type type = req->get_type(); double op_start = timestamp(); stats::scoped_read_write_timer read_write_timer(bytes, type == request::WRITE); void * mem = mmap(NULL, bytes, PROT_READ | PROT_WRITE, MAP_SHARED, file_des, offset); if (mem == MAP_FAILED) { STXXL_THROW2(io_error, " Mapping failed." << " Page size: " << sysconf(_SC_PAGESIZE) << " offset modulo page size " << (offset % sysconf(_SC_PAGESIZE))); } else if (mem == 0) { stxxl_function_error(io_error); } else { if (type == request::READ) { memcpy(buffer, mem, bytes); } else { memcpy(mem, buffer, bytes); } stxxl_check_ge_0(munmap(mem, bytes), io_error); } double delay = get_delay(offset, bytes); delay = delay - timestamp() + op_start; assert(delay > 0.0); int seconds_to_wait = static_cast(floor(delay)); if (seconds_to_wait) sleep(seconds_to_wait); usleep((unsigned long)((delay - seconds_to_wait) * 1000000.)); } const char * sim_disk_file::io_type() const { return "simdisk"; } //////////////////////////////////////////////////////////////////////////// void sim_disk_file::set_size(offset_type newsize) { scoped_mutex_lock fd_lock(fd_mutex); if (newsize > _size()) { stxxl_check_ge_0(::lseek(file_des, newsize - 1, SEEK_SET), io_error); stxxl_check_ge_0(::write(file_des, "", 1), io_error); } } __STXXL_END_NAMESPACE #endif // #if STXXL_HAVE_SIMDISK_FILE // vim: et:ts=4:sw=4 stxxl-1.3.1/io/benchmark_disk_and_flash.cpp0000644000175000017500000001157311305236156020601 0ustar andreasandreas/*************************************************************************** * io/benchmark_disk_and_flash.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2008 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #include #include #include #include #ifndef BOOST_MSVC #include #endif using stxxl::request_ptr; using stxxl::file; using stxxl::timestamp; #ifdef BLOCK_ALIGN #undef BLOCK_ALIGN #endif #define BLOCK_ALIGN 4096 #define KB (1024) #define MB (1024 * 1024) #define GB (1024 * 1024 * 1024) void run(char * buffer, file ** disks, stxxl::int64 offset, stxxl::int64 length, unsigned hdd_blocks, unsigned hdd_bytes, unsigned ssd_blocks, unsigned ssd_bytes, unsigned repeats) { unsigned i, j; double begin = timestamp(), end, elapsed; request_ptr * reqs = new request_ptr[stxxl::STXXL_MAX(hdd_blocks + ssd_blocks, 1U)]; struct diskinfo { unsigned id; unsigned bytes; unsigned n; }; diskinfo info[2]; // HDD info[0].id = 0; info[0].bytes = hdd_bytes; info[0].n = hdd_blocks; // SSD info[1].id = 1; info[1].bytes = ssd_bytes; info[1].n = ssd_blocks; begin = timestamp(); double volume = 0; for (unsigned repeat = 0; repeat < repeats; ++repeat) { int r = 0; char * buf = buffer; for (i = 0; i < 2; i++) { for (j = 0; j < info[i].n; j++) { stxxl::int64 bytes = info[i].bytes; stxxl::int64 position = (bytes * (rand() & 0xffff)) % length; reqs[r++] = disks[info[i].id]->aread(buf, offset + position, bytes, stxxl::default_completion_handler()); buf += bytes; volume += bytes; } } wait_all(reqs, r); } end = timestamp(); elapsed = end - begin; std::cout << "B_d = " << info[0].bytes << " B_f = " << info[1].bytes << " n_d = " << info[0].n << " n_f = " << info[1].n; //<< std::endl; std::cout << " Transferred " << (volume / MB) << " MiB in " << elapsed << " seconds @ " << (volume / MB / elapsed) << " MiB/s" << std::endl; delete[] reqs; } void usage(const char * argv0) { std::cout << "Usage: " << argv0 << " offset length diskfile flashfile" << std::endl; std::cout << " starting 'offset' and 'length' are given in GiB" << std::endl; std::cout << " length == 0 implies till end of space (please ignore the write error)" << std::endl; exit(-1); } int main(int argc, char * argv[]) { if (argc < 4) usage(argv[0]); stxxl::int64 offset = stxxl::int64(GB) * stxxl::int64(atoi(argv[1])); stxxl::int64 length = stxxl::int64(GB) * stxxl::int64(atoi(argv[2])); int first_disk_arg = 3; std::vector disks_arr; if (!(first_disk_arg < argc)) usage(argv[0]); for (int ii = first_disk_arg; ii < argc; ii++) { std::cout << "# Add disk: " << argv[ii] << std::endl; disks_arr.push_back(argv[ii]); } const unsigned ndisks = disks_arr.size(); stxxl::int64 buffer_size = 1024 * MB; const stxxl::int64 buffer_size_int = buffer_size / sizeof(int); unsigned i; file ** disks = new file *[ndisks]; unsigned * buffer = (unsigned *)stxxl::aligned_alloc(buffer_size); for (i = 0; i < buffer_size_int; i++) buffer[i] = i; for (i = 0; i < ndisks; i++) { disks[i] = new stxxl::syscall_file(disks_arr[i], file::CREAT | file::RDWR | file::DIRECT, i); } try { run((char *)buffer, disks, offset, length, 1, 2 * MB, 23, 128 * 1024, 100); run((char *)buffer, disks, offset, length, 1, 2 * MB, 42, 128 * 1024, 100); for (unsigned hdd_bytes = 4 * KB; hdd_bytes < 256 * MB; hdd_bytes <<= 1) { for (unsigned ssd_bytes = 128 * KB; ssd_bytes == 128 * KB; ssd_bytes <<= 1) { for (unsigned hdd_blocks = 1; hdd_blocks == 1; ++hdd_blocks) { for (unsigned ssd_blocks = 0; ssd_blocks <= (stxxl::STXXL_MAX(16U, 2 * hdd_bytes * hdd_blocks / ssd_bytes)); ++ssd_blocks) { run((char *)buffer, disks, offset, length, hdd_blocks, hdd_bytes, ssd_blocks, ssd_bytes, 100); } } } } } catch (const std::exception & ex) { std::cout << std::endl; STXXL_ERRMSG(ex.what()); } for (i = 0; i < ndisks; i++) delete disks[i]; delete[] disks; stxxl::aligned_dealloc(buffer); return 0; } // vim: et:ts=4:sw=4 stxxl-1.3.1/io/GNUmakefile0000644000175000017500000000073011340547616015202 0ustar andreasandreasTOPDIR ?= .. include Makefile.common -include $(TOPDIR)/make.settings.local ENABLE_UNITTEST ?= no TESTS-yes += $(TESTS_NON_MSVC) TESTS-$(ENABLE_UNITTEST) += $(TESTS_UNITTEST) include $(TOPDIR)/Makefile.subdir.gnu tools: $(UTIL_BINARIES:=.$(bin)) # requires libcppunit-dev to be installed unittest.$o: CPPFLAGS += $(CPPUNIT_COMPILER_OPTIONS) -Wno-error unittest.$(bin): STXXL_LINKER_OPTIONS += $(CPPUNIT_LINKER_OPTIONS) clean:: $(RM) $(UTIL_BINARIES:=.$(bin)) stxxl-1.3.1/io/test_io.cpp0000644000175000017500000000600611531445437015304 0ustar andreasandreas/*************************************************************************** * io/test_io.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2002 Roman Dementiev * Copyright (C) 2008, 2009 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #include #include #include //! \example io/test_io.cpp //! This is an example of use of \c \ files, requests, and //! completion tracking mechanisms, i.e. \c stxxl::file , \c stxxl::request using stxxl::file; struct my_handler { void operator () (stxxl::request * ptr) { STXXL_MSG("Request completed: " << ptr); } }; int main(int argc, char ** argv) { if (argc < 2) { std::cout << "Usage: " << argv[0] << " tempdir" << std::endl; return -1; } std::string tempfilename[2]; tempfilename[0] = std::string(argv[1]) + "/test_io_1.dat"; tempfilename[1] = std::string(argv[1]) + "/test_io_2.dat"; std::cout << sizeof(void *) << std::endl; const int size = 1024 * 384; char * buffer = (char *)stxxl::aligned_alloc<4096>(size); memset(buffer, 0, size); #ifndef BOOST_MSVC stxxl::mmap_file file1(tempfilename[0], file::CREAT | file::RDWR /* | file::DIRECT */, 0); file1.set_size(size * 1024); #endif stxxl::syscall_file file2(tempfilename[1], file::CREAT | file::RDWR /* | file::DIRECT */, 1); stxxl::request_ptr req[16]; unsigned i; for (i = 0; i < 16; i++) req[i] = file2.awrite(buffer, i * size, size, my_handler()); wait_all(req, 16); // check behaviour of having requests to the same location at the same time for (i = 2; i < 16; i++) req[i] = file2.awrite(buffer, 0, size, my_handler()); req[0] = file2.aread(buffer, 0, size, my_handler()); req[1] = file2.awrite(buffer, 0, size, my_handler()); wait_all(req, 16); stxxl::aligned_dealloc<4096>(buffer); std::cout << *(stxxl::stats::get_instance()); stxxl::uint64 sz; for (sz = 123, i = 0; i < 20; ++i, sz *= 10) STXXL_MSG(">>>" << stxxl::add_SI_multiplier(sz) << "<<<"); for (sz = 123, i = 0; i < 20; ++i, sz *= 10) STXXL_MSG(">>>" << stxxl::add_SI_multiplier(sz, "B") << "<<<"); STXXL_MSG(">>>" << stxxl::add_SI_multiplier((std::numeric_limits::max)(), "B") << "<<<"); for (sz = 123, i = 0; i < 20; ++i, sz *= 10) STXXL_MSG(">>>" << stxxl::add_IEC_binary_multiplier(sz) << "<<<"); for (sz = 123, i = 0; i < 20; ++i, sz *= 10) STXXL_MSG(">>>" << stxxl::add_IEC_binary_multiplier(sz, "B") << "<<<"); STXXL_MSG(">>>" << stxxl::add_IEC_binary_multiplier((std::numeric_limits::max)(), "B") << "<<<"); unlink(tempfilename[0].c_str()); unlink(tempfilename[1].c_str()); return 0; } stxxl-1.3.1/io/wbtl_file.cpp0000644000175000017500000003110711535151017015575 0ustar andreasandreas/*************************************************************************** * io/wbtl_file.cpp * * a write-buffered-translation-layer pseudo file * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2008-2009 Andreas Beckmann * Copyright (C) 2009 Johannes Singler * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #include #if STXXL_HAVE_WBTL_FILE #include #include #include #include #include #ifndef STXXL_VERBOSE_WBTL #define STXXL_VERBOSE_WBTL STXXL_VERBOSE2 #endif __STXXL_BEGIN_NAMESPACE wbtl_file::wbtl_file( file * backend_file, size_type write_buffer_size, int write_buffers, int queue_id, int allocator_id) : disk_queued_file(queue_id, allocator_id), storage(backend_file), sz(0), write_block_size(write_buffer_size), free_bytes(0), curbuf(1), curpos(write_block_size) { assert(write_buffers == 2); // currently hardcoded write_buffer[0] = static_cast(stxxl::aligned_alloc(write_block_size)); write_buffer[1] = static_cast(stxxl::aligned_alloc(write_block_size)); buffer_address[0] = offset_type(-1); buffer_address[1] = offset_type(-1); } wbtl_file::~wbtl_file() { stxxl::aligned_dealloc(write_buffer[1]); stxxl::aligned_dealloc(write_buffer[0]); delete storage; storage = 0; } void wbtl_file::serve(const request * req) throw (io_error) { assert(req->get_file() == this); offset_type offset = req->get_offset(); void * buffer = req->get_buffer(); size_type bytes = req->get_size(); request::request_type type = req->get_type(); if (type == request::READ) { //stats::scoped_read_timer read_timer(size()); sread(buffer, offset, bytes); } else { //stats::scoped_write_timer write_timer(size()); swrite(buffer, offset, bytes); } } void wbtl_file::lock() { storage->lock(); } wbtl_file::offset_type wbtl_file::size() { return sz; } void wbtl_file::set_size(offset_type newsize) { scoped_mutex_lock mapping_lock(mapping_mutex); assert(sz <= newsize); // may not shrink if (sz < newsize) { _add_free_region(sz, newsize - sz); storage->set_size(newsize); sz = newsize; assert(sz == storage->size()); } } #define FMT_A_S(_addr_, _size_) "0x" << std::hex << std::setfill('0') << std::setw(8) << (_addr_) << "/0x" << std::setw(8) << (_size_) #define FMT_A_C(_addr_, _size_) "0x" << std::setw(8) << (_addr_) << "(" << std::dec << (_size_) << ")" #define FMT_A(_addr_) "0x" << std::setw(8) << (_addr_) // logical address void wbtl_file::discard(offset_type offset, offset_type size) { scoped_mutex_lock mapping_lock(mapping_mutex); sortseq::iterator physical = address_mapping.find(offset); STXXL_VERBOSE_WBTL("wbtl:discard l" << FMT_A_S(offset, size) << " @ p" << FMT_A(physical != address_mapping.end() ? physical->second : 0xffffffff)); if (physical == address_mapping.end()) { // could be OK if the block was never written ... //STXXL_ERRMSG("discard: mapping not found: " << FMT_A_S(offset, size) << " ==> " << "???"); } else { offset_type physical_offset = physical->second; address_mapping.erase(physical); _add_free_region(physical_offset, size); place_map::iterator reverse = reverse_mapping.find(physical_offset); if (reverse == reverse_mapping.end()) { STXXL_ERRMSG("discard: reverse mapping not found: " << FMT_A_S(offset, size) << " ==> " << "???"); } else { assert(offset == (reverse->second).first); reverse_mapping.erase(reverse); } storage->discard(physical_offset, size); } } // physical address void wbtl_file::_add_free_region(offset_type offset, offset_type size) { // mapping_lock has to be aquired by caller STXXL_VERBOSE_WBTL("wbtl:addfre p" << FMT_A_S(offset, size) << " F <= f" << FMT_A_C(free_bytes, free_space.size())); offset_type region_pos = offset; offset_type region_size = size; if (!free_space.empty()) { sortseq::iterator succ = free_space.upper_bound(region_pos); sortseq::iterator pred = succ; pred--; check_corruption(region_pos, region_size, pred, succ); if (succ == free_space.end()) { if (pred == free_space.end()) { //dump(); assert(pred != free_space.end()); } if ((*pred).first + (*pred).second == region_pos) { // coalesce with predecessor region_size += (*pred).second; region_pos = (*pred).first; free_space.erase(pred); } } else { if (free_space.size() > 1) { bool succ_is_not_the_first = (succ != free_space.begin()); if ((*succ).first == region_pos + region_size) { // coalesce with successor region_size += (*succ).second; free_space.erase(succ); } if (succ_is_not_the_first) { if (pred == free_space.end()) { //dump(); assert(pred != free_space.end()); } if ((*pred).first + (*pred).second == region_pos) { // coalesce with predecessor region_size += (*pred).second; region_pos = (*pred).first; free_space.erase(pred); } } } else { if ((*succ).first == region_pos + region_size) { // coalesce with successor region_size += (*succ).second; free_space.erase(succ); } } } } free_space[region_pos] = region_size; free_bytes += size; STXXL_VERBOSE_WBTL("wbtl:free p" << FMT_A_S(region_pos, region_size) << " F => f" << FMT_A_C(free_bytes, free_space.size())); } void wbtl_file::sread(void * buffer, offset_type offset, size_type bytes) { scoped_mutex_lock buffer_lock(buffer_mutex); int cached = -1; offset_type physical_offset; // map logical to physical address { scoped_mutex_lock mapping_lock(mapping_mutex); sortseq::iterator physical = address_mapping.find(offset); if (physical == address_mapping.end()) { STXXL_ERRMSG("wbtl_read: mapping not found: " << FMT_A_S(offset, bytes) << " ==> " << "???"); //STXXL_THROW2(io_error, "wbtl_read of unmapped memory"); physical_offset = 0xffffffff; } else { physical_offset = physical->second; } } if (buffer_address[curbuf] <= physical_offset && physical_offset < buffer_address[curbuf] + write_block_size) { // block is in current write buffer assert(physical_offset + bytes <= buffer_address[curbuf] + write_block_size); memcpy(buffer, write_buffer[curbuf] + (physical_offset - buffer_address[curbuf]), bytes); stats::get_instance()->read_cached(bytes); cached = curbuf; } else if (buffer_address[1 - curbuf] <= physical_offset && physical_offset < buffer_address[1 - curbuf] + write_block_size) { // block is in previous write buffer assert(physical_offset + bytes <= buffer_address[1 - curbuf] + write_block_size); memcpy(buffer, write_buffer[1 - curbuf] + (physical_offset - buffer_address[1 - curbuf]), bytes); stats::get_instance()->read_cached(bytes); cached = curbuf; } else if (physical_offset == 0xffffffff) { // block was deleted or never written before char * uninitialized = (char *)malloc(sizeof(char)); memset(buffer, *uninitialized, bytes); free(uninitialized); } else { // block is not cached request_ptr req = storage->aread(buffer, physical_offset, bytes, default_completion_handler()); req->wait(false); } STXXL_VERBOSE_WBTL("wbtl:sread l" << FMT_A_S(offset, bytes) << " @ p" << FMT_A(physical_offset) << " " << std::dec << cached); STXXL_UNUSED(cached); } void wbtl_file::swrite(void * buffer, offset_type offset, size_type bytes) { scoped_mutex_lock buffer_lock(buffer_mutex); // is the block already mapped? { scoped_mutex_lock mapping_lock(mapping_mutex); sortseq::iterator physical = address_mapping.find(offset); STXXL_VERBOSE_WBTL("wbtl:swrite l" << FMT_A_S(offset, bytes) << " @ <= p" << FMT_A_C(physical != address_mapping.end() ? physical->second : 0xffffffff, address_mapping.size())); if (physical != address_mapping.end()) { mapping_lock.unlock(); // FIXME: special case if we can replace it in the current writing block discard(offset, bytes); } } if (bytes > write_block_size - curpos) { // not enough space in the current write buffer if (buffer_address[curbuf] != offset_type(-1)) { STXXL_VERBOSE_WBTL("wbtl:w2disk p" << FMT_A_S(buffer_address[curbuf], write_block_size)); // mark remaining part as free if (curpos < write_block_size) _add_free_region(buffer_address[curbuf] + curpos, write_block_size - curpos); if (backend_request.get()) { backend_request->wait(false); } backend_request = storage->awrite(write_buffer[curbuf], buffer_address[curbuf], write_block_size, default_completion_handler()); } curbuf = 1 - curbuf; buffer_address[curbuf] = get_next_write_block(); curpos = 0; } assert(bytes <= write_block_size - curpos); // write block into buffer memcpy(write_buffer[curbuf] + curpos, buffer, bytes); stats::get_instance()->write_cached(bytes); scoped_mutex_lock mapping_lock(mapping_mutex); address_mapping[offset] = buffer_address[curbuf] + curpos; reverse_mapping[buffer_address[curbuf] + curpos] = place(offset, bytes); STXXL_VERBOSE_WBTL("wbtl:swrite l" << FMT_A_S(offset, bytes) << " @ => p" << FMT_A_C(buffer_address[curbuf] + curpos, address_mapping.size())); curpos += bytes; } wbtl_file::offset_type wbtl_file::get_next_write_block() { // mapping_lock has to be aquired by caller sortseq::iterator space = std::find_if(free_space.begin(), free_space.end(), bind2nd(FirstFit(), write_block_size) _STXXL_FORCE_SEQUENTIAL); if (space != free_space.end()) { offset_type region_pos = (*space).first; offset_type region_size = (*space).second; free_space.erase(space); if (region_size > write_block_size) free_space[region_pos + write_block_size] = region_size - write_block_size; free_bytes -= write_block_size; STXXL_VERBOSE_WBTL("wbtl:nextwb p" << FMT_A_S(region_pos, write_block_size) << " F f" << FMT_A_C(free_bytes, free_space.size())); return region_pos; } STXXL_THROW2(io_error, "OutOfSpace, probably fragmented"); return offset_type(-1); } void wbtl_file::check_corruption(offset_type region_pos, offset_type region_size, sortseq::iterator pred, sortseq::iterator succ) { if (pred != free_space.end()) { if (pred->first <= region_pos && pred->first + pred->second > region_pos) { STXXL_THROW(bad_ext_alloc, "wbtl_file::check_corruption", "Error: double deallocation of external memory " << "System info: P " << pred->first << " " << pred->second << " " << region_pos); } } if (succ != free_space.end()) { if (region_pos <= succ->first && region_pos + region_size > succ->first) { STXXL_THROW(bad_ext_alloc, "wbtl_file::check_corruption", "Error: double deallocation of external memory " << "System info: S " << region_pos << " " << region_size << " " << succ->first); } } } const char * wbtl_file::io_type() const { return "wbtl"; } __STXXL_END_NAMESPACE #endif // #if STXXL_HAVE_WBTL_FILE // vim: et:ts=4:sw=4 stxxl-1.3.1/io/mem_file.cpp0000644000175000017500000000411111535547223015406 0ustar andreasandreas/*************************************************************************** * io/mem_file.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2008 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #include #include #include __STXXL_BEGIN_NAMESPACE void mem_file::serve(const request * req) throw (io_error) { assert(req->get_file() == this); offset_type offset = req->get_offset(); void * buffer = req->get_buffer(); size_type bytes = req->get_size(); request::request_type type = req->get_type(); if (type == request::READ) { stats::scoped_read_timer read_timer(bytes); memcpy(buffer, ptr + offset, bytes); } else { stats::scoped_write_timer write_timer(bytes); memcpy(ptr + offset, buffer, bytes); } } const char * mem_file::io_type() const { return "memory"; } mem_file::~mem_file() { delete[] ptr; ptr = NULL; } void mem_file::lock() { // nothing to do } file::offset_type mem_file::size() { return sz; } void mem_file::set_size(offset_type newsize) { assert(ptr == NULL); // no resizing if (ptr == NULL) ptr = new char[sz = newsize]; } void mem_file::discard(offset_type offset, offset_type size) { #ifndef STXXL_MEMFILE_DONT_CLEAR_FREED_MEMORY // overwrite the freed region with uninitialized memory STXXL_VERBOSE("discard at " << offset << " len " << size); void * uninitialized = malloc(BLOCK_ALIGN); while (size >= BLOCK_ALIGN) { memcpy(ptr + offset, uninitialized, BLOCK_ALIGN); offset += BLOCK_ALIGN; size -= BLOCK_ALIGN; } if (size > 0) memcpy(ptr + offset, uninitialized, size); free(uninitialized); #else STXXL_UNUSED(offset); STXXL_UNUSED(size); #endif } __STXXL_END_NAMESPACE stxxl-1.3.1/io/request_queue_impl_1q.cpp0000644000175000017500000000743611535655573020174 0ustar andreasandreas/*************************************************************************** * io/request_queue_impl_1q.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2002-2005 Roman Dementiev * Copyright (C) 2009 Andreas Beckmann * Copyright (C) 2009 Johannes Singler * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #include #include #include #include #ifndef STXXL_CHECK_FOR_PENDING_REQUESTS_ON_SUBMISSION #define STXXL_CHECK_FOR_PENDING_REQUESTS_ON_SUBMISSION 1 #endif __STXXL_BEGIN_NAMESPACE struct file_offset_match : public std::binary_function { bool operator () ( const request_ptr & a, const request_ptr & b) const { // matching file and offset are enough to cause problems return (a->get_offset() == b->get_offset()) && (a->get_file() == b->get_file()); } }; request_queue_impl_1q::request_queue_impl_1q(int n) : _thread_state(NOT_RUNNING), sem(0) { STXXL_UNUSED(n); start_thread(worker, static_cast(this), thread, _thread_state); } void request_queue_impl_1q::add_request(request_ptr & req) { if (req.empty()) STXXL_THROW_INVALID_ARGUMENT("Empty request submitted to disk_queue."); if (_thread_state() != RUNNING) STXXL_THROW_INVALID_ARGUMENT("Request submitted to not running queue."); #if STXXL_CHECK_FOR_PENDING_REQUESTS_ON_SUBMISSION { scoped_mutex_lock Lock(queue_mutex); if (std::find_if(queue.begin(), queue.end(), bind2nd(file_offset_match(), req) _STXXL_FORCE_SEQUENTIAL) != queue.end()) { STXXL_ERRMSG("request submitted for a BID with a pending request"); } } #endif scoped_mutex_lock Lock(queue_mutex); queue.push_back(req); sem++; } bool request_queue_impl_1q::cancel_request(request_ptr & req) { if (req.empty()) STXXL_THROW_INVALID_ARGUMENT("Empty request canceled disk_queue."); if (_thread_state() != RUNNING) STXXL_THROW_INVALID_ARGUMENT("Request canceled to not running queue."); bool was_still_in_queue = false; { scoped_mutex_lock Lock(queue_mutex); queue_type::iterator pos; if ((pos = std::find(queue.begin(), queue.end(), req _STXXL_FORCE_SEQUENTIAL)) != queue.end()) { queue.erase(pos); was_still_in_queue = true; sem--; } } return was_still_in_queue; } request_queue_impl_1q::~request_queue_impl_1q() { stop_thread(thread, _thread_state, sem); } void * request_queue_impl_1q::worker(void * arg) { self * pthis = static_cast(arg); request_ptr req; for ( ; ; ) { pthis->sem--; { scoped_mutex_lock Lock(pthis->queue_mutex); if (!pthis->queue.empty()) { req = pthis->queue.front(); pthis->queue.pop_front(); Lock.unlock(); //assert(req->nref() > 1); req->serve(); } else { Lock.unlock(); pthis->sem++; } } // terminate if it has been requested and queues are empty if (pthis->_thread_state() == TERMINATE) { if ((pthis->sem--) == 0) break; else pthis->sem++; } } return NULL; } __STXXL_END_NAMESPACE // vim: et:ts=4:sw=4 stxxl-1.3.1/io/Makefile.common0000644000175000017500000000133311535563072016057 0ustar andreasandreasTESTS = test_io test_io_sizes gen_file test_cancel flushbuffers benchmark_disk_and_flash benchmark_configured_disks benchmark_random_block_access iobench_scatter_in_place verify_disks TESTS_NON_MSVC = sd_test TESTS_UNITTEST = unittest UTIL_BINARIES = benchmark_disks LIB_SRC = \ iostats.cpp \ request.cpp \ request_with_state.cpp \ request_with_waiters.cpp \ serving_request.cpp \ disk_queued_file.cpp \ request_queue_impl_worker.cpp \ request_queue_impl_qwqr.cpp \ request_queue_impl_1q.cpp \ ufs_file_base.cpp \ syscall_file.cpp \ mmap_file.cpp \ simdisk_file.cpp \ wfs_file_base.cpp \ wincall_file.cpp \ boostfd_file.cpp \ fileperblock_file.cpp \ wbtl_file.cpp \ mem_file.cpp \ create_file.cpp stxxl-1.3.1/io/serving_request.cpp0000644000175000017500000000377111535564521017071 0ustar andreasandreas/*************************************************************************** * io/serving_request.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2002 Roman Dementiev * Copyright (C) 2008 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #include #include #include __STXXL_BEGIN_NAMESPACE serving_request::serving_request( const completion_handler & on_cmpl, file * f, void * buf, offset_type off, size_type b, request_type t) : request_with_state(on_cmpl, f, buf, off, b, t) { #ifdef STXXL_CHECK_BLOCK_ALIGNING // Direct I/O requires file system block size alignment for file offsets, // memory buffer addresses, and transfer(buffer) size must be multiple // of the file system block size check_alignment(); #endif } void serving_request::serve() { check_nref(); STXXL_VERBOSE2( "[" << static_cast(this) << "] serving_request::serve(): " << buffer << " @ [" << file_ << "|" << file_->get_allocator_id() << "]0x" << std::hex << std::setfill('0') << std::setw(8) << offset << "/0x" << bytes << ((type == request::READ) ? " READ" : " WRITE")); try { file_->serve(this); } catch (const io_error & ex) { error_occured(ex.what()); } check_nref(true); completed(); } void serving_request::completed() { STXXL_VERBOSE2("[" << static_cast(this) << "] serving_request::completed()"); _state.set_to(DONE); request_with_state::completed(); _state.set_to(READY2DIE); } const char * serving_request::io_type() const { return file_->io_type(); } __STXXL_END_NAMESPACE // vim: et:ts=4:sw=4 stxxl-1.3.1/io/iobench_scatter_in_place.cpp0000644000175000017500000001727011533725150020624 0ustar andreasandreas/*************************************************************************** * io/iobench_scatter_in_place.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2009 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #include #include #include #include #include #include using stxxl::request_ptr; using stxxl::file; using stxxl::timer; using stxxl::uint64; #ifndef BLOCK_ALIGN #define BLOCK_ALIGN 4096 #endif #define MB (1024 * 1024) #define GB (1024 * 1024 * 1024) void usage(const char * argv0) { std::cout << "Usage: " << argv0 << " num_blocks blocks_per_round block_size file" << std::endl; std::cout << " 'block_size' in bytes" << std::endl; std::cout << " 'file' is split into 'num_blocks' files of size 'block_size'," << std::endl; std::cout << " reading chunks of 'blocks_per_round' blocks starting from end-of-file" << std::endl; std::cout << " and truncating the input file after each chunk was read," << std::endl; std::cout << " before writing the chunk to new files" << std::endl; exit(-1); } // returns throughput in MiB/s inline double throughput(double bytes, double seconds) { if (seconds == 0.0) return 0.0; return bytes / (1024 * 1024) / seconds; } int main(int argc, char * argv[]) { if (argc < 5) usage(argv[0]); uint64 num_blocks = stxxl::atoint64(argv[1]); uint64 blocks_per_round = stxxl::atoint64(argv[2]); uint64 block_size = stxxl::atoint64(argv[3]); const char * filebase = argv[4]; uint64 num_rounds = stxxl::div_ceil(num_blocks, blocks_per_round); std::cout << "# Splitting '" << filebase << "' into " << num_rounds * blocks_per_round << " blocks of size " << block_size << ", reading chunks of " << blocks_per_round << " blocks" << std::endl; char * buffer = (char *)stxxl::aligned_alloc(block_size * blocks_per_round); double totaltimeread = 0, totaltimewrite = 0; stxxl::int64 totalsizeread = 0, totalsizewrite = 0; double totaltimereadchunk = 0.0, totaltimewritechunk = 0.0; stxxl::int64 totalsizereadchunk = 0, totalsizewritechunk = 0; typedef stxxl::syscall_file file_type; file_type input_file(filebase, file::RDWR | file::DIRECT, 0); timer t_total(true); try { for (stxxl::unsigned_type r = num_rounds; r-- > 0; ) { // read a chunk of blocks_per_round blocks timer t_read(true); for (stxxl::unsigned_type i = blocks_per_round; i-- > 0; ) { const uint64 offset = (r * blocks_per_round + i) * block_size; timer t_op(true); // read a block { input_file.aread(buffer + i * block_size, offset, block_size, stxxl::default_completion_handler())->wait(); } t_op.stop(); totalsizeread += block_size; totaltimeread += t_op.seconds(); if (blocks_per_round > 1) { std::cout << "Offset " << std::setw(8) << offset / MB << " MiB: " << std::fixed; std::cout << std::setw(8) << std::setprecision(3) << throughput(block_size, t_op.seconds()) << " MiB/s read"; std::cout << std::endl; } } // truncate input_file.set_size(r * blocks_per_round * block_size); t_read.stop(); totalsizereadchunk += blocks_per_round * block_size; totaltimereadchunk += t_read.seconds(); // write the chunk timer t_write(true); for (stxxl::unsigned_type i = blocks_per_round; i-- > 0; ) { const uint64 offset = (r * blocks_per_round + i) * block_size; timer t_op(true); // write a block { char cfn[4096]; // PATH_MAX snprintf(cfn, sizeof(cfn), "%s_%012llX", filebase, offset); file_type chunk_file(cfn, file::CREAT | file::RDWR | file::DIRECT, 0); chunk_file.awrite(buffer + i * block_size, 0, block_size, stxxl::default_completion_handler())->wait(); } t_op.stop(); totalsizewrite += block_size; totaltimewrite += t_op.seconds(); if (blocks_per_round > 1) { std::cout << "Offset " << std::setw(8) << offset / MB << " MiB: " << std::fixed; std::cout << std::setw(8) << std::setprecision(3) << "" << " "; std::cout << std::setw(8) << std::setprecision(3) << throughput(block_size, t_op.seconds()) << " MiB/s write"; std::cout << std::endl; } } t_write.stop(); totalsizewritechunk += blocks_per_round * block_size; totaltimewritechunk += t_write.seconds(); const uint64 offset = r * blocks_per_round * block_size; std::cout << "Input offset " << std::setw(8) << offset / MB << " MiB: " << std::fixed; std::cout << std::setw(8) << std::setprecision(3) << throughput(block_size * blocks_per_round, t_read.seconds()) << " MiB/s read, "; std::cout << std::setw(8) << std::setprecision(3) << throughput(block_size * blocks_per_round, t_write.seconds()) << " MiB/s write"; std::cout << std::endl; } } catch (const std::exception & ex) { std::cout << std::endl; STXXL_ERRMSG(ex.what()); } t_total.stop(); const int ndisks = 1; std::cout << "=============================================================================================" << std::endl; std::cout << "# Average over " << std::setw(8) << stxxl::STXXL_MAX(totalsizewrite, totalsizeread) / MB << " MiB: "; std::cout << std::setw(8) << std::setprecision(3) << (throughput(totalsizeread, totaltimeread)) << " MiB/s read, "; std::cout << std::setw(8) << std::setprecision(3) << (throughput(totalsizewrite, totaltimewrite)) << " MiB/s write" << std::endl; if (totaltimeread != 0.0) std::cout << "# Read time " << std::setw(8) << std::setprecision(3) << totaltimeread << " s" << std::endl; if (totaltimereadchunk != 0.0) std::cout << "# ChRd/trnk ti " << std::setw(8) << std::setprecision(3) << totaltimereadchunk << " s" << std::endl; if (totaltimewrite != 0.0) std::cout << "# Write time " << std::setw(8) << std::setprecision(3) << totaltimewrite << " s" << std::endl; if (totaltimewritechunk != 0.0) std::cout << "# ChWrite time " << std::setw(8) << std::setprecision(3) << totaltimewritechunk << " s" << std::endl; std::cout << "# Non-I/O time " << std::setw(8) << std::setprecision(3) << (t_total.seconds() - totaltimewrite - totaltimeread) << " s, average throughput " << std::setw(8) << std::setprecision(3) << (throughput(totalsizewrite + totalsizeread, t_total.seconds() - totaltimewrite - totaltimeread) * ndisks) << " MiB/s" << std::endl; std::cout << "# Total time " << std::setw(8) << std::setprecision(3) << t_total.seconds() << " s, average throughput " << std::setw(8) << std::setprecision(3) << (throughput(totalsizewrite + totalsizeread, t_total.seconds()) * ndisks) << " MiB/s" << std::endl; stxxl::aligned_dealloc(buffer); return 0; } // vim: et:ts=4:sw=4 stxxl-1.3.1/io/ufs_file_base.cpp0000644000175000017500000001043011536140702016410 0ustar andreasandreas/*************************************************************************** * io/ufs_file_base.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2002, 2005, 2008 Roman Dementiev * Copyright (C) 2008 Ilja Andronov * Copyright (C) 2008-2010 Andreas Beckmann * Copyright (C) 2009 Johannes Singler * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #include #include #ifdef BOOST_MSVC #include #else #include #include #endif #include __STXXL_BEGIN_NAMESPACE const char * ufs_file_base::io_type() const { return "ufs_base"; } ufs_file_base::ufs_file_base( const std::string & filename, int mode) : file_des(-1), mode_(mode), filename(filename) { int flags = 0; if (mode & RDONLY) { flags |= O_RDONLY; } if (mode & WRONLY) { flags |= O_WRONLY; } if (mode & RDWR) { flags |= O_RDWR; } if (mode & CREAT) { flags |= O_CREAT; } if (mode & TRUNC) { flags |= O_TRUNC; } #ifndef STXXL_DIRECT_IO_OFF if (mode & DIRECT) { flags |= O_DIRECT; } #endif if (mode & SYNC) { flags |= O_RSYNC; flags |= O_DSYNC; flags |= O_SYNC; } #ifdef BOOST_MSVC flags |= O_BINARY; // the default in MS is TEXT mode #endif #ifdef BOOST_MSVC const int perms = S_IREAD | S_IWRITE; #else const int perms = S_IREAD | S_IWRITE | S_IRGRP | S_IWGRP; #endif if ((file_des = ::open(filename.c_str(), flags, perms)) < 0) STXXL_THROW2(io_error, "::open() rc=" << file_des << " path=" << filename << " flags=" << flags); if (!(mode & NO_LOCK)) { lock(); } } ufs_file_base::~ufs_file_base() { close(); } void ufs_file_base::close() { scoped_mutex_lock fd_lock(fd_mutex); if (file_des == -1) return; if (::close(file_des) < 0) stxxl_function_error(io_error); file_des = -1; } void ufs_file_base::lock() { #ifdef BOOST_MSVC // not yet implemented #else scoped_mutex_lock fd_lock(fd_mutex); struct flock lock_struct; lock_struct.l_type = (mode_ & RDONLY) ? F_RDLCK : F_RDLCK | F_WRLCK; lock_struct.l_whence = SEEK_SET; lock_struct.l_start = 0; lock_struct.l_len = 0; // lock all bytes if ((::fcntl(file_des, F_SETLK, &lock_struct)) < 0) STXXL_THROW2(io_error, "::fcntl(,F_SETLK,) path=" << filename << " fd=" << file_des); #endif } file::offset_type ufs_file_base::_size() { #ifdef BOOST_MSVC struct _stat64 st; stxxl_check_ge_0(_fstat64(file_des, &st), io_error); #else struct stat st; stxxl_check_ge_0(::fstat(file_des, &st), io_error); #endif return st.st_size; } file::offset_type ufs_file_base::size() { scoped_mutex_lock fd_lock(fd_mutex); return _size(); } void ufs_file_base::set_size(offset_type newsize) { scoped_mutex_lock fd_lock(fd_mutex); offset_type cur_size = _size(); if (!(mode_ & RDONLY)) { #ifdef BOOST_MSVC HANDLE hfile; stxxl_check_ge_0(hfile = (HANDLE) ::_get_osfhandle(file_des), io_error); LARGE_INTEGER desired_pos; desired_pos.QuadPart = newsize; if (!SetFilePointerEx(hfile, desired_pos, NULL, FILE_BEGIN)) stxxl_win_lasterror_exit("SetFilePointerEx in ufs_file_base::set_size(..) oldsize=" << cur_size << " newsize=" << newsize << " ", io_error); if (!SetEndOfFile(hfile)) stxxl_win_lasterror_exit("SetEndOfFile oldsize=" << cur_size << " newsize=" << newsize << " ", io_error); #else stxxl_check_ge_0(::ftruncate(file_des, newsize), io_error); #endif } #ifndef BOOST_MSVC if (newsize > cur_size) stxxl_check_ge_0(::lseek(file_des, newsize - 1, SEEK_SET), io_error); #endif } void ufs_file_base::remove() { close(); ::remove(filename.c_str()); } __STXXL_END_NAMESPACE // vim: et:ts=4:sw=4 stxxl-1.3.1/io/request_queue_impl_qwqr.cpp0000644000175000017500000001405411535655573020637 0ustar andreasandreas/*************************************************************************** * io/request_queue_impl_qwqr.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2002-2005 Roman Dementiev * Copyright (C) 2008, 2009 Andreas Beckmann * Copyright (C) 2009 Johannes Singler * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #include #include #include #include #ifndef STXXL_CHECK_FOR_PENDING_REQUESTS_ON_SUBMISSION #define STXXL_CHECK_FOR_PENDING_REQUESTS_ON_SUBMISSION 1 #endif __STXXL_BEGIN_NAMESPACE struct file_offset_match : public std::binary_function { bool operator () ( const request_ptr & a, const request_ptr & b) const { // matching file and offset are enough to cause problems return (a->get_offset() == b->get_offset()) && (a->get_file() == b->get_file()); } }; request_queue_impl_qwqr::request_queue_impl_qwqr(int n) : _thread_state(NOT_RUNNING), sem(0) { STXXL_UNUSED(n); start_thread(worker, static_cast(this), thread, _thread_state); } void request_queue_impl_qwqr::add_request(request_ptr & req) { if (req.empty()) STXXL_THROW_INVALID_ARGUMENT("Empty request submitted to disk_queue."); if (_thread_state() != RUNNING) STXXL_THROW_INVALID_ARGUMENT("Request submitted to not running queue."); if (req.get()->get_type() == request::READ) { #if STXXL_CHECK_FOR_PENDING_REQUESTS_ON_SUBMISSION { scoped_mutex_lock Lock(write_mutex); if (std::find_if(write_queue.begin(), write_queue.end(), bind2nd(file_offset_match(), req) _STXXL_FORCE_SEQUENTIAL) != write_queue.end()) { STXXL_ERRMSG("READ request submitted for a BID with a pending WRITE request"); } } #endif scoped_mutex_lock Lock(read_mutex); read_queue.push_back(req); } else { #if STXXL_CHECK_FOR_PENDING_REQUESTS_ON_SUBMISSION { scoped_mutex_lock Lock(read_mutex); if (std::find_if(read_queue.begin(), read_queue.end(), bind2nd(file_offset_match(), req) _STXXL_FORCE_SEQUENTIAL) != read_queue.end()) { STXXL_ERRMSG("WRITE request submitted for a BID with a pending READ request"); } } #endif scoped_mutex_lock Lock(write_mutex); write_queue.push_back(req); } sem++; } bool request_queue_impl_qwqr::cancel_request(request_ptr & req) { if (req.empty()) STXXL_THROW_INVALID_ARGUMENT("Empty request canceled disk_queue."); if (_thread_state() != RUNNING) STXXL_THROW_INVALID_ARGUMENT("Request canceled to not running queue."); bool was_still_in_queue = false; if (req.get()->get_type() == request::READ) { scoped_mutex_lock Lock(read_mutex); queue_type::iterator pos; if ((pos = std::find(read_queue.begin(), read_queue.end(), req _STXXL_FORCE_SEQUENTIAL)) != read_queue.end()) { read_queue.erase(pos); was_still_in_queue = true; sem--; } } else { scoped_mutex_lock Lock(write_mutex); queue_type::iterator pos; if ((pos = std::find(write_queue.begin(), write_queue.end(), req _STXXL_FORCE_SEQUENTIAL)) != write_queue.end()) { write_queue.erase(pos); was_still_in_queue = true; sem--; } } return was_still_in_queue; } request_queue_impl_qwqr::~request_queue_impl_qwqr() { stop_thread(thread, _thread_state, sem); } void * request_queue_impl_qwqr::worker(void * arg) { self * pthis = static_cast(arg); request_ptr req; bool write_phase = true; for ( ; ; ) { pthis->sem--; if (write_phase) { scoped_mutex_lock WriteLock(pthis->write_mutex); if (!pthis->write_queue.empty()) { req = pthis->write_queue.front(); pthis->write_queue.pop_front(); WriteLock.unlock(); //assert(req->nref() > 1); req->serve(); } else { WriteLock.unlock(); pthis->sem++; if (pthis->_priority_op == WRITE) write_phase = false; } if (pthis->_priority_op == NONE || pthis->_priority_op == READ) write_phase = false; } else { scoped_mutex_lock ReadLock(pthis->read_mutex); if (!pthis->read_queue.empty()) { req = pthis->read_queue.front(); pthis->read_queue.pop_front(); ReadLock.unlock(); STXXL_VERBOSE2("queue: before serve request has " << req->nref() << " references "); //assert(req->nref() > 1); req->serve(); STXXL_VERBOSE2("queue: after serve request has " << req->nref() << " references "); } else { ReadLock.unlock(); pthis->sem++; if (pthis->_priority_op == READ) write_phase = true; } if (pthis->_priority_op == NONE || pthis->_priority_op == WRITE) write_phase = true; } // terminate if it has been requested and queues are empty if (pthis->_thread_state() == TERMINATE) { if ((pthis->sem--) == 0) break; else pthis->sem++; } } return NULL; } __STXXL_END_NAMESPACE // vim: et:ts=4:sw=4 stxxl-1.3.1/io/wfs_file_base.cpp0000644000175000017500000001272511535151017016423 0ustar andreasandreas/*************************************************************************** * io/wfs_file_base.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2005 Roman Dementiev * Copyright (C) 2008, 2010 Andreas Beckmann * Copyright (C) 2009, 2010 Johannes Singler * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #include #ifdef BOOST_MSVC __STXXL_BEGIN_NAMESPACE const char * wfs_file_base::io_type() const { return "wfs_base"; } static HANDLE open_file_impl(const std::string & filename, int mode) { DWORD dwDesiredAccess = 0; DWORD dwShareMode = 0; DWORD dwCreationDisposition = 0; DWORD dwFlagsAndAttributes = 0; if (mode & file::RDONLY) { dwFlagsAndAttributes |= FILE_ATTRIBUTE_READONLY; dwDesiredAccess |= GENERIC_READ; } if (mode & file::WRONLY) { dwDesiredAccess |= GENERIC_WRITE; } if (mode & file::RDWR) { dwDesiredAccess |= (GENERIC_READ | GENERIC_WRITE); } if (mode & file::CREAT) { // ignored } if (mode & file::TRUNC) { dwCreationDisposition |= TRUNCATE_EXISTING; } else { dwCreationDisposition |= OPEN_ALWAYS; } #ifndef STXXL_DIRECT_IO_OFF if (mode & file::DIRECT) { dwFlagsAndAttributes |= FILE_FLAG_NO_BUFFERING; // TODO: try also FILE_FLAG_WRITE_THROUGH option ? } #endif if (mode & file::SYNC) { // ignored } HANDLE file_des = ::CreateFile(filename.c_str(), dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, dwFlagsAndAttributes, NULL); if (file_des == INVALID_HANDLE_VALUE) stxxl_win_lasterror_exit("CreateFile filename=" << filename, io_error); return file_des; } wfs_file_base::wfs_file_base( const std::string & filename, int mode) : file_des(INVALID_HANDLE_VALUE), mode_(mode), filename(filename), locked(false) { file_des = open_file_impl(filename, mode); if (!(mode & NO_LOCK)) { lock(); } if (!(mode_ & RDONLY) && (mode & DIRECT)) { char buf[32768], * part; if (!GetFullPathName(filename.c_str(), sizeof(buf), buf, &part)) { STXXL_ERRMSG("wfs_file_base::wfs_file_base(): GetFullPathName() error for file " << filename); bytes_per_sector = 512; } else { part[0] = char(); DWORD bytes_per_sector_; if (!GetDiskFreeSpace(buf, NULL, &bytes_per_sector_, NULL, NULL)) { STXXL_ERRMSG("wfs_file_base::wfs_file_base(): GetDiskFreeSpace() error for path " << buf); bytes_per_sector = 512; } else bytes_per_sector = bytes_per_sector_; } } } wfs_file_base::~wfs_file_base() { close(); } void wfs_file_base::close() { scoped_mutex_lock fd_lock(fd_mutex); if (file_des == INVALID_HANDLE_VALUE) return; if (!CloseHandle(file_des)) stxxl_win_lasterror_exit("closing file (call of ::CloseHandle) ", io_error); file_des = INVALID_HANDLE_VALUE; } void wfs_file_base::lock() { scoped_mutex_lock fd_lock(fd_mutex); if (locked) return; // already locked if (LockFile(file_des, 0, 0, 0xffffffff, 0xffffffff) == 0) stxxl_win_lasterror_exit("LockFile ", io_error); locked = true; } file::offset_type wfs_file_base::_size() { LARGE_INTEGER result; if (!GetFileSizeEx(file_des, &result)) stxxl_win_lasterror_exit("GetFileSizeEx ", io_error); return result.QuadPart; } file::offset_type wfs_file_base::size() { scoped_mutex_lock fd_lock(fd_mutex); return _size(); } void wfs_file_base::set_size(offset_type newsize) { scoped_mutex_lock fd_lock(fd_mutex); offset_type cur_size = _size(); if (!(mode_ & RDONLY)) { LARGE_INTEGER desired_pos; desired_pos.QuadPart = newsize; bool direct_with_bad_size = (mode_ & file::DIRECT) && (newsize % bytes_per_sector); if (direct_with_bad_size) { if (!CloseHandle(file_des)) stxxl_win_lasterror_exit("closing file (call of ::CloseHandle from set_size) ", io_error); file_des = INVALID_HANDLE_VALUE; file_des = open_file_impl(filename, WRONLY); } if (!SetFilePointerEx(file_des, desired_pos, NULL, FILE_BEGIN)) stxxl_win_lasterror_exit("SetFilePointerEx in wfs_file_base::set_size(..) oldsize=" << cur_size << " newsize=" << newsize << " ", io_error); if (!SetEndOfFile(file_des)) stxxl_win_lasterror_exit("SetEndOfFile oldsize=" << cur_size << " newsize=" << newsize << " ", io_error); if (direct_with_bad_size) { if (!CloseHandle(file_des)) stxxl_win_lasterror_exit("closing file (call of ::CloseHandle from set_size) ", io_error); file_des = INVALID_HANDLE_VALUE; file_des = open_file_impl(filename, mode_ & ~TRUNC); } } } void wfs_file_base::remove() { close(); ::DeleteFile(filename.c_str()); } __STXXL_END_NAMESPACE #endif // #ifdef BOOST_MSVC // vim: et:ts=4:sw=4 stxxl-1.3.1/io/mmap_file.cpp0000644000175000017500000000426011536140702015557 0ustar andreasandreas/*************************************************************************** * io/mmap_file.cpp * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2002 Roman Dementiev * Copyright (C) 2008 Andreas Beckmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #include #if STXXL_HAVE_MMAP_FILE #include #include __STXXL_BEGIN_NAMESPACE void mmap_file::serve(const request * req) throw (io_error) { scoped_mutex_lock fd_lock(fd_mutex); assert(req->get_file() == this); offset_type offset = req->get_offset(); void * buffer = req->get_buffer(); size_type bytes = req->get_size(); request::request_type type = req->get_type(); stats::scoped_read_write_timer read_write_timer(bytes, type == request::WRITE); int prot = (type == request::READ) ? PROT_READ : PROT_WRITE; void * mem = mmap(NULL, bytes, prot, MAP_SHARED, file_des, offset); // void *mem = mmap (buffer, bytes, prot , MAP_SHARED|MAP_FIXED , file_des, offset); // STXXL_MSG("Mmaped to "< * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ /* example gnuplot command for the output of this program: (x-axis: offset in GiB, y-axis: bandwidth in MiB/s) plot \ "disk.log" using ($2/1024):($7) w l title "read", \ "disk.log" using ($2/1024):($4) w l title "write" */ #include #include #include #include #ifndef BOOST_MSVC #include #endif using stxxl::request_ptr; using stxxl::file; using stxxl::timestamp; #ifdef BLOCK_ALIGN #undef BLOCK_ALIGN #endif #define BLOCK_ALIGN 4096 #define POLL_DELAY 1000 #define CHECK_AFTER_READ 0 #define MB (1024 * 1024) #define GB (1024 * 1024 * 1024) void usage(const char * argv0) { std::cout << "Usage: " << argv0 << " length step [r|w]" << std::endl; std::cout << " 'length' is given in GiB, 'step' size in MiB" << std::endl; std::cout << " length == 0 implies till end of space (please ignore the write error)" << std::endl; exit(-1); } int main(int argc, char * argv[]) { if (argc < 3) usage(argv[0]); stxxl::int64 offset = 0; stxxl::int64 length = stxxl::int64(GB) * stxxl::int64(atoi(argv[1])); stxxl::int64 step_size = stxxl::int64(MB) * stxxl::int64(atoi(argv[2])); stxxl::int64 endpos = offset + length; bool do_read = true, do_write = true; if (argc == 4 && (strcmp("r", argv[3]) == 0 || strcmp("R", argv[3]) == 0)) do_write = false; if (argc == 4 && (strcmp("w", argv[3]) == 0 || strcmp("W", argv[3]) == 0)) do_read = false; const unsigned raw_block_size = 8 * MB; const unsigned block_size = raw_block_size / sizeof(int); typedef stxxl::typed_block block_type; typedef stxxl::BID BID_type; unsigned num_blocks_per_step = stxxl::div_ceil(step_size, raw_block_size); step_size = num_blocks_per_step * raw_block_size; block_type * buffer = new block_type[num_blocks_per_step]; request_ptr * reqs = new request_ptr[num_blocks_per_step]; std::vector blocks; double totaltimeread = 0, totaltimewrite = 0; stxxl::int64 totalsizeread = 0, totalsizewrite = 0; std::cout << "# Step size: " << stxxl::add_IEC_binary_multiplier(step_size, "B") << " (" << num_blocks_per_step << " blocks of " << stxxl::add_IEC_binary_multiplier(raw_block_size, "B") << ")" << std::endl; //touch data, so it is actually allcoated for (unsigned j = 0; j < num_blocks_per_step; ++j) for (unsigned i = 0; i < block_size; ++i) buffer[j][i] = j * block_size + i; try { STXXL_DEFAULT_ALLOC_STRATEGY alloc; while (offset < endpos) { const stxxl::int64 current_step_size = std::min(step_size, endpos - offset); #if CHECK_AFTER_READ const stxxl::int64 current_step_size_int = current_step_size / sizeof(int); #endif const unsigned current_num_blocks_per_step = stxxl::div_ceil(current_step_size, raw_block_size); std::cout << "Offset " << std::setw(7) << offset / MB << " MiB: " << std::fixed; stxxl::unsigned_type num_total_blocks = blocks.size(); blocks.resize(num_total_blocks + current_num_blocks_per_step); stxxl::block_manager::get_instance()->new_blocks(alloc, blocks.begin() + num_total_blocks, blocks.end()); double begin = timestamp(), end, elapsed; if (do_write) { for (unsigned j = 0; j < current_num_blocks_per_step; j++) reqs[j] = buffer[j].write(blocks[num_total_blocks + j]); wait_all(reqs, current_num_blocks_per_step); end = timestamp(); elapsed = end - begin; totalsizewrite += current_step_size; totaltimewrite += elapsed; } else elapsed = 0.0; std::cout << std::setw(5) << std::setprecision(1) << (double(current_step_size) / MB / elapsed) << " MiB/s write, "; begin = timestamp(); if (do_read) { for (unsigned j = 0; j < current_num_blocks_per_step; j++) reqs[j] = buffer[j].read(blocks[num_total_blocks + j]); wait_all(reqs, current_num_blocks_per_step); end = timestamp(); elapsed = end - begin; totalsizeread += current_step_size; totaltimeread += elapsed; } else elapsed = 0.0; std::cout << std::setw(5) << std::setprecision(1) << (double(current_step_size) / MB / elapsed) << " MiB/s read" << std::endl; #if CHECK_AFTER_READ for (unsigned j = 0; j < current_num_blocks_per_step; j++) { for (unsigned i = 0; i < block_size; i++) { if (buffer[j][i] != j * block_size + i) { int ibuf = i / current_step_size_int; int pos = i % current_step_size_int; std::cout << "Error on disk " << ibuf << " position " << std::hex << std::setw(8) << offset + pos * sizeof(int) << " got: " << std::hex << std::setw(8) << buffer[j][i] << " wanted: " << std::hex << std::setw(8) << (j * block_size + i) << std::dec << std::endl; i = (ibuf + 1) * current_step_size_int; // jump to next } } } #endif offset += current_step_size; } } catch (const std::exception & ex) { std::cout << std::endl; STXXL_ERRMSG(ex.what()); } std::cout << "=============================================================================================" << std::endl; std::cout << "# Average over " << std::setw(7) << totalsizewrite / MB << " MiB: "; std::cout << std::setw(5) << std::setprecision(1) << (double(totalsizewrite) / MB / totaltimewrite) << " MiB/s write, "; std::cout << std::setw(5) << std::setprecision(1) << (double(totalsizeread) / MB / totaltimeread) << " MiB/s read" << std::endl; delete[] reqs; delete[] buffer; return 0; } stxxl-1.3.1/stxxl.sln0000644000175000017500000000242711046361576014430 0ustar andreasandreasMicrosoft Visual Studio Solution File, Format Version 9.00 # Visual C++ Express 2005 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "stxxl", "stxxl.vcproj", "{26082884-8591-49FC-BA2E-471EA5236214}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 Library and tests|Win32 = Library and tests|Win32 Library|Win32 = Library|Win32 Release|Win32 = Release|Win32 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {26082884-8591-49FC-BA2E-471EA5236214}.Debug|Win32.ActiveCfg = Library|Win32 {26082884-8591-49FC-BA2E-471EA5236214}.Debug|Win32.Build.0 = Library|Win32 {26082884-8591-49FC-BA2E-471EA5236214}.Library and tests|Win32.ActiveCfg = Library and tests|Win32 {26082884-8591-49FC-BA2E-471EA5236214}.Library and tests|Win32.Build.0 = Library and tests|Win32 {26082884-8591-49FC-BA2E-471EA5236214}.Library|Win32.ActiveCfg = Library|Win32 {26082884-8591-49FC-BA2E-471EA5236214}.Library|Win32.Build.0 = Library|Win32 {26082884-8591-49FC-BA2E-471EA5236214}.Release|Win32.ActiveCfg = Library|Win32 {26082884-8591-49FC-BA2E-471EA5236214}.Release|Win32.Build.0 = Library|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection EndGlobal stxxl-1.3.1/doxymain.h0000644000175000017500000007206511521474003014522 0ustar andreasandreas/*! \mainpage Documentation for STXXL library * * \image html layer_diagram.png * *

* The core of \c STXXL is an implementation of the C++ * standard template library STL for external memory (out-of-core) * computations, i.e., \c STXXL implements containers and algorithms * that can process huge volumes of data that only fit on * disks. While the compatibility to the STL supports * ease of use and compatibility with existing applications, * another design priority is high performance. * Here is a selection of \c STXXL performance features: * - transparent support of multiple disks * - variable block lengths * - overlapping of I/O and computation * - prevention of OS file buffering overhead * - algorithm pipelining * - utilization of multiple processor cores for internal computation * * * \section platforms Supported Operating Systems * - Linux (kernel >= 2.4.18) * - Mac OS X * - FreeBSD * - other POSIX compatible systems should work, but have not been tested * - Windows 2000/XP/Vista/7 * * * \section compilers Supported Compilers * * The following compilers have been tested in different * \c STXXL configurations. * Other compilers might work, too, but we don't have the resources * (systems, compilers or time) to test them. * Feedback is welcome. * * The compilers marked with '*' are the developer's favorite choices * and are most thoroughly tested. * * \verbatim | parallel parallel | stxxl stxxl stxxl stxxl compiler | + boost + boost ----------------+---------------------------------------- GCC 4.5 c++0x | x PMODE² - - GCC 4.5 | x PMODE² - - * GCC 4.4 c++0x | x PMODE² x PMODE² GCC 4.4 | x PMODE² x PMODE² GCC 4.3 c++0x | x PMODE² x PMODE² GCC 4.3 | x PMODE² x PMODE² GCC 4.2 | x MCSTL x MCSTL GCC 4.1 | x - x - GCC 4.0 | x - x - GCC 3.4 | x - x - GCC 3.3 | o - o - GCC 2.95 | - - - - ICPC 12.0.107 | x¹ PMODE°¹ x¹ PMODE°¹ ICPC 12.0.107 | x¹ MCSTL¹ x¹ MCSTL¹ * ICPC 11.1.075 | x¹ MCSTL¹ x¹ MCSTL¹ ICPC 11.0.084 | x¹ MCSTL¹ x¹ MCSTL¹ ICPC 10.1.026 | x¹ MCSTL¹ x¹ MCSTL¹ ICPC 10.0.026 | x¹ MCSTL¹ x¹ MCSTL¹ ICPC 9.1.053 | x¹ - x¹ - ICPC 9.0.032 | x¹ - x¹ - clang++ 2.8 | x³ - x³ - MSVC 2010 10.0| - - x - * MSVC 2008 9.0 | - - x - MSVC 2005 8.0 | - - x - x = full support o = partial support - = unsupported ? = untested MCSTL = supports parallelization using the MCSTL library PMODE = supports parallelization using libstdc++ parallel mode ° = needs workaround -D__aligned__=ignored ¹ = you may have to add a -gcc-name= option if the system default gcc does not come in the correct version: icpc 9.0: use with gcc 3.x icpc 9.1: use with gcc before 4.2 icpc 10.x, 11.x, 12.0 with mcstl support: use with gcc 4.2 icpc 12.0 with pmode support: use with gcc 4.3 ² = MCSTL has been superseded by the libstdc++ parallel mode in gcc 4.3, full support requires gcc 4.4 or later, only partial support in gcc 4.3 ³ = with libstdc++ from gcc 4.2 \endverbatim * * * \section boost Supported BOOST versions * * The Boost libraries are required on * Windows platforms using MSVC compiler and optional on other platforms. * * \c STXXL has been tested with Boost 1.40.0 and 1.42.0. * Other versions may work, too, but older versions will not get support. * * * \section installation Instructions on installation, usage, configuration * * - \link installation_linux_gcc Installation, usage, configuration (Linux/Unix – g++/icpc/clang++) \endlink * - \link installation_msvc Installation, usage, configuration (Windows – Microsoft Visual C++) \endlink * * - \link install-svn Installing from subversion \endlink * * * \section questions Questions * * - Questions concerning use and development of the \c STXXL * library should be posted to the * FORUMS. * Please search the forum before posting, * your question may have been answered before. * * \section bugreports Bug Reports * * - Bugs should be reported in the * Bugzilla Bug Tracker * * - \link FAQ FAQ - Frequently Asked Questions \endlink * * * \section license License * * \c STXXL is distributed under the Boost Software License, Version 1.0.
* You can find a copy of the license in the accompanying file \c LICENSE_1_0.txt or online at * http://www.boost.org/LICENSE_1_0.txt. */ /*! * \page FAQ FAQ - Frequently Asked Questions * * \section FAQ-latest Latest version of this FAQ * The most recent version of this FAQ can always be found * here. * * * \section q1 References to Elements in External Memory Data Structures * * You should not pass or store references to elements in an external memory * data structure. When the reference is used, the block that contains the * element may be no longer in internal memory.
* Use/pass an iterator (reference) instead.
* For an \c stxxl::vector with \c n pages and LRU replacement strategy, it * can be guaranteed that the last \c n references * obtained using \c stxxl::vector::operator[] or dereferencing * an iterator are valid. * However, if \c n is 1, even a single innocent-looking line like * \verbatim std::cout << v[0] << " " << v[1000000] << std::endl; \endverbatim can lead to * inconsistent results. *
* * * \section q2 Parameterizing STXXL Containers * * STXXL container types like stxxl::vector can be parameterized only with a value type that is a * POD * (i. e. no virtual functions, no user-defined copy assignment/destructor, etc.) * and does not contain references (including pointers) to internal memory. * Usually, "complex" data types do not satisfy this requirements. * * This is why stxxl::vector > and stxxl::vector > are invalid. * If appropriate, use std::vector >, or emulate a two-dimensional array by * doing index calculation. * * * \section q3 Thread-Safety * * The I/O and block management layers are thread-safe (since release 1.1.1). * The user layer data structures are not thread-safe.
* I.e. you may access different \c STXXL data structures from concurrent threads without problems, * but you should not share a data structure between threads (without implementing proper locking yourself).
* This is a design choice, having the data structures thread-safe would mean a significant performance loss. * * * \section q4 I have configured several disks to use with STXXL. Why does STXXL fail complaining about the lack of space? According to my calclulations, the space on the disks should be sufficient. * * This may happen if the disks have different size. With the default parameters \c STXXL containers use randomized block-to-disk allocation strategies * that distribute data evenly between the disks but ignore the availability of free space on them. * * * \section q5 STXXL in a Microsoft CLR Library * * From STXXL user Christian, posted in the forum: * * Precondition: I use STXXL in a Microsoft CLR Library (a special DLL). That means that managed code and native code (e.g. STXXL) have to co-exist in your library. * * Symptom: Application crashes at process exit, when the DLL is unloaded. * * Cause: STXXL's singleton classes use the \c atexit() function to destruct themselves at process exit. The exit handling will cause the process to crash at exit (still unclear if it's a bug or a feature of the MS runtime). * * Solution: * * 1.) Compiled STXXL static library with \c STXXL_NON_DEFAULT_EXIT_HANDLER defined. * * 2.) For cleanup, \c stxxl::run_exit_handlers() has now to be called manually. To get this done automatically: * * Defined a CLI singleton class "Controller": * * \verbatim public ref class Controller { private: static Controller^ instance = gcnew Controller; Controller(); }; \endverbatim * * Registered my own cleanup function in Controller's constructor which will manage to call \c stxxl::run_exit_handlers(): * * \verbatim #pragma managed(push, off) static int myexitfn() { stxxl::run_exit_handlers(); return 0; } #pragma managed(pop) Controller::Controller() { onexit(myexitfn); } \endverbatim * * * \section q6 How can I credit STXXL, and thus foster its development? * * - For all users: * - Sign up at Ohloh and add yourself as an STXXL user / rate STXXL: http://www.ohloh.net/p/stxxl * - Rate STXXL at heise Software-Verzeichnis (German): http://www.heise.de/software/download/stxxl/76072 * - Rate STXXL at SourceForge: https://sourceforge.net/projects/stxxl/ * * - For scientific work: Cite the papers mentioned here: http://stxxl.sourceforge.net/ * * - For industrial users: Tell us the name of your company, so we can use it as a reference. * */ /*! * \page install Instructions on Installation, usage, configuration * - \link installation_linux_gcc Installation, usage, configuration (Linux/Unix – g++/icpc/clang++) \endlink * - \link installation_msvc Installation, usage, configuration (Windows – Microsoft Visual C++) \endlink * * - \link install-svn Installing from subversion \endlink */ /*! * \page installation_linux_gcc Installation, usage, configuration (Linux/Unix – g++/icpc/clang++) * * \section download_linux_gcc Download and Extraction * * - Download the latest gzipped tarball from * SourceForge * - Unpack in some directory executing: \c tar \c zfxv \c stxxl-x.y.z.tgz * - Change to \c stxxl directory: \c cd \c stxxl-x.y.z * * \section library_compilation_linux_gcc Library Compilation * * - Run: \verbatim make config_gnu \endverbatim to create a template \c make.settings.local file. * Note: this will produce some warnings and abort with an error, which is intended. * - (optionally) change the \c make.settings.local file according to your system configuration: * - (optionally) set the \c STXXL_ROOT variable to \c STXXL root directory * ( \c directory_where_you_unpacked_the_tar_ball/stxxl-x.y.z ) * - if you want \c STXXL to use Boost libraries * (you should have the Boost libraries already installed) * - change the \c USE_BOOST variable to \c yes * - change the \c BOOST_ROOT variable to the Boost root path, unless Boost is installed in system default search paths. * - if you want \c STXXL to use the libstdc++ parallel mode * - use GCC version 4.3 or later * - use the targets \c library_g++_pmode and \c tests_g++_pmode instead of the ones listed below * - if you want \c STXXL to use the MCSTL * library (you should have the MCSTL library already installed) * - change the \c MCSTL_ROOT variable to the MCSTL root path * - use the targets \c library_g++_mcstl and \c tests_g++_mcstl instead of the ones listed below * - (optionally) set the \c OPT variable to \c -O3 or other g++ optimization level you like (default: \c -O3 ) * - (optionally) set the \c DEBUG variable to \c -g or other g++ debugging option * if you want to produce a debug version of the Stxxl library or Stxxl examples (default: not set) * - for more variables to tune take a look at \c make.settings.gnu , * they are usually overridden by settings in \c make.settings.local, * using \c CPPFLAGS and \c LDFLAGS, for example, you can add arbitrary compiler and linker options * - Run: \verbatim make library_g++ \endverbatim * - Run: \verbatim make tests_g++ \endverbatim (optional, if you want to compile and run some test programs) * * * \section build_apps Building an Application * * After compiling the library, some Makefile variables are written to * \c stxxl.mk (\c pmstxxl.mk if you have built with parallel mode, \c mcstxxl.mk if you have built with MCSTL) in your * \c STXXL_ROOT directory. This file should be included from your * application's Makefile. * * The following variables can be used: * - \c STXXL_CXX - the compiler used to build the \c STXXL * library, it's recommended to use the same to build your applications * - \c STXXL_CPPFLAGS - add these flags to the compile commands * - \c STXXL_LDLIBS - add these libraries to the link commands * * An example Makefile for an application using \c STXXL: * \verbatim STXXL_ROOT ?= .../stxxl STXXL_CONFIG ?= stxxl.mk include $(STXXL_ROOT)/$(STXXL_CONFIG) # use the variables from stxxl.mk CXX = $(STXXL_CXX) CPPFLAGS += $(STXXL_CPPFLAGS) LDLIBS += $(STXXL_LDLIBS) # add your own optimization, warning, debug, ... flags # (these are *not* set in stxxl.mk) CPPFLAGS += -O3 -Wall -g -DFOO=BAR # build your application # (my_example.o is generated from my_example.cpp automatically) my_example.bin: my_example.o $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(LDFLAGS) my_example.o -o $@ $(LDLIBS) \endverbatim * * \section parallel Enabling parallel execution * * To enable (shared-memory-)parallel execution of internal computation (in fact, sorting and merging, and random shuffling), * you have several options depending on the \ref compilers "compiler version" used: * - Enable the g++ parallel mode specifically for STXXL, * by defining \c STXXL_PARALLEL_MODE_EXPLICIT and enabling OpenMP (\c -DSTXXL_PARALLEL_MODE_EXPLICIT \c -fopenmp) * during compilation and linkage of your program. * Compiling the library binary with this flag enabled is not really necessary, * since the most time-consuming operations are called by the generic routines and thus contained in the header files. * - Enable the g++ parallel mode for your program globally, * by defining \c _GLIBCXX_PARALLEL and enabling OpenMP (\c -D_GLIBCXX_PARALLEL \c -fopenmp). * This has the implication that STL algorithms in your program will also be executed in parallel, * which may have undesired side effects. * These options are automatically used when you built STXXL using the \c *_pmode target, * and your Makefile includes \c pmstxxl.mk. * - Enable MCSTL in your program by setting the include path appropriately. * This implies that STL algorithms in your program will also be executed in parallel, * which may have undesired side effects. * These options are automatically used when you built STXXL using the \c *_mcstl target, * and your Makefile includes \c mcstxxl.mk. * * We recommend to try the first option at first. * * The number of threads to be used can be set by the environment variable OMP_NUM_THREADS or * by calling omp_set_num_threads. * Detailed tuning can be achieved as described * here. * * * \section space Disk space * * Before you try to run one of the \c STXXL examples * (or your own \c STXXL program) you must configure the disk * space that will be used as external memory for the library. * * To get best performance with \c STXXL you should assign separate disks to it. * These disks should be used by the library only. * Since \c STXXL is developed to exploit disk parallelism, the performance of your * external memory application will increase if you use more than one disk. * But from how many disks your application can benefit depends on how "I/O bound" it is. * With modern disk bandwidths * of about 50-75 MiB/s most of applications are I/O bound for one disk. This means that if you add another disk * the running time will be halved. Adding more disks might also increase performance significantly. * * * \section filesystem Recommended file system * * The library benefits from direct transfers from user memory to disk, which saves superfluous copies. * We recommend to use the * \c XFS file system, * which gives good read and write performance for large files. * Note that file creation speed of \c XFS is a bit slower, * so that disk files should be precreated for optimal performance. * * If the filesystems only use is to store one large \c STXXL disk file, * we also recommend to add the following options to the \c mkfs.xfs command to gain maximum performance: * \verbatim -d agcount=1 -l size=512b \endverbatim * * The following filesystems have been reported not to support direct I/O: \c tmpfs , \c glusterfs . * Since direct I/O is enabled by default, you may recompile \c STXXL * with \c STXXL_DIRECT_IO_OFF defined to access files on these file systems. * * * \section configuration Disk configuration file * * You must define the disk configuration for an * \c STXXL program in a file named \c '.stxxl' that must reside * in the same directory where you execute the program. * You can change the default file name for the configuration * file by setting the environment variable \c STXXLCFG . * * Each line of the configuration file describes a disk. * A disk description uses the following format:
* \c disk=full_disk_filename,capacity,access_method * * Description of the parameters: * - \c full_disk_filename : full disk filename. In order to access disks STXXL uses file * access methods. Each disk is represented as a file. If you have a disk that is mounted in Unix * to the path /mnt/disk0/, then the correct value for the \c full_disk_filename would be * \c /mnt/disk0/some_file_name , * - \c capacity : maximum capacity of the disk in megabytes * (0 means autogrow, file will be deleted afterwards) * - \c access_method : \c STXXL has a number of different * file access implementations for POSIX systems, choose one of them: * - \c syscall : use \c read and \c write system calls which perform disk transfers directly * on user memory pages without superfluous copying (currently the fastest method) * - \c mmap : \c use \c mmap and \c munmap system calls * - \c boostfd : access the file using a Boost file descriptor * - \c fileperblock_syscall, \c fileperblock_mmap, \c fileperblock_boostfd : * same as above, but take a single file per block, using full_disk_filename as file name prefix. * Usually provide worse performance than the standard variants, * but release freed blocks to the file system immediately. * - \c simdisk : simulates timings of the IBM IC35L080AVVA07 disk, full_disk_filename must point * to a file on a RAM disk partition with sufficient space * - \c memory : keeps all data in RAM, for quicker testing * - \c wbtl : library-based write-combining (good for writing small blocks onto SSDs), * based on \c syscall * * See also the example configuration file \c 'config_example' included in the tarball. * * * \section logfiles Log files * * \c STXXL produces two kinds of log files, a message and an error log. * By setting the environment variables \c STXXLLOGFILE and \c STXXLERRLOGFILE, you can configure * the location of these files. * The default values are \c stxxl.log and \c stxxl.errlog, respectively. * * * \section excreation Precreating external memory files * * In order to get the maximum performance one should precreate disk files described in the configuration file, * before running \c STXXL applications. * * The precreation utility is included in the set of \c STXXL * utilities ( \c utils/createdisks.bin ). Run this utility * for each disk you have defined in the disk configuration file: * \verbatim utils/createdisks.bin capacity full_disk_filename... \endverbatim * * */ /*! * \page installation_msvc Installation, usage, configuration (Windows – Microsoft Visual C++) * * \section download_msvc Download and Extraction * * - Install the Boost libraries (required). * - Download the latest \c Stxxl zip file from * SourceForge * - Unpack the zip file in some directory (e. g. \c 'C:\\' ) * - Change to \c stxxl base directory: \c cd \c stxxl-x.y.z * * \section library_compilation_msvc Library Compilation * * - Create \c make.settings.local in the base directory according to your system configuration: * - set \c BOOST_ROOT variable according to the Boost root path, e. g. * BOOST_ROOT = "C:\Program Files (x86)\boost\boost_1_40_0"# * - (optionally) set \c STXXL_ROOT variable to \c STXXL root directory * - (optionally) set \c OPT variable to \c /O2 or any other VC++ optimization level you like, * add -D_SECURE_SCL=0 to switch off iterator checking, which improves performance * - (optionally) set \c DEBUG_COMPILER=/MDd /Zi and DEBUG_LINKER=/DEBUG enable debugging * - Open the \c stxxl.vcproj file (VS Solution Object) in Visual Studio. * The file is located in the \c STXXL_ROOT directory * Press F7 to build the library. * The library file (libstxxl.lib) should appear in \c STXXL_ROOT\\lib directory * Or build the library and the STXXL test programs by pressing Ctrl-Alt-F7 * (or choosing from 'Build' drop-down menu Rebuild Solution) * - (alternatively) Compile the library by executing \c nmake \c library_msvc * and the tests by executing \c nmake \c tests_msvc, * with all the appropriate environment set (e. g. by using the VS Command Shell) * * * \section build_apps Building an application * * Programs using Stxxl can be compiled using options from \c compiler.options * file (in the \c STXXL_ROOT directory). The linking options for the VC++ * linker you can find in \c linker.options file. In order to accomplish this * do the following: * - Open project property pages (menu Project->Properties) * - Choose C/C++->Command Line page. * - In the 'Additional Options' field insert the contents of the \c compiler.options file. * Make sure that the Runtime libraries/debug options (/MDd or /MD or /MT or /MTd) of * the \c Stxxl library (see above) do not conflict with the options of your project. * Use the same options in the \c Stxxl and your project. * - Choose Linker->Command Line page. * - In the 'Additional Options' field insert the contents of the \c linker.options file. * *
* If you use make files you can * include the \c make.settings file in your make files and use \c STXXL_COMPILER_OPTIONS and * \c STXXL_LINKER_OPTIONS variables, defined therein. * * For example:
* \verbatim cl -c my_example.cpp $(STXXL_COMPILER_OPTIONS) \endverbatim
* \verbatim link my_example.obj /out:my_example.exe $(STXXL_LINKER_OPTIONS) \endverbatim * *
* The \c STXXL_ROOT\\test\\WinGUI directory contains an example MFC GUI project * that uses \c Stxxl. In order to compile it open the WinGUI.vcproj file in * Visual Studio .NET. Change if needed the Compiler and Linker Options of the project * (see above). * * Before you try to run one of the \c STXXL examples * (or your own \c STXXL program) you must configure the disk * space that will be used as external memory for the library. For instructions how to do that, * see the next section. * * * \section space Disk space * * To get best performance with \c STXXL you should assign separate disks to it. * These disks should be used by the library only. * Since \c STXXL is developed to exploit disk parallelism, the performance of your * external memory application will increase if you use more than one disk. * But from how many disks your application can benefit depends on how "I/O bound" it is. * With modern disk bandwidths * of about 50-75 MiB/s most of applications are I/O bound for one disk. This means that if you add another disk * the running time will be halved. Adding more disks might also increase performance significantly. * * * \section configuration Disk configuration file * * You must define the disk configuration for an * \c STXXL program in a file named \c '.stxxl' that must reside * in the same directory where you execute the program. * You can change the default file name for the configuration * file by setting the environment variable \c STXXLCFG . * * Each line of the configuration file describes a disk. * A disk description uses the following format:
* \c disk=full_disk_filename,capacity,access_method * * Description of the parameters: * - \c full_disk_filename : full disk filename. In order to access disks STXXL uses file * access methods. Each disk is represented as a file. If you have a disk called \c e: * then the correct value for the \c full_disk_filename would be * \c e:\\some_file_name , * - \c capacity : maximum capacity of the disk in megabytes * - \c access_method : \c STXXL has a number of different * file access implementations for WINDOWS, choose one of them: * - \c syscall : use \c read and \c write POSIX system calls (slow) * - \c wincall: performs disks transfers using \c ReadFile and \c WriteFile WinAPI calls * This method supports direct I/O that avoids superfluous copying of data pages * in the Windows kernel. This is the best (and default) method in Stxxl for Windows. * - \c boostfd : access the file using a Boost file descriptor * - \c fileperblock_syscall, \c fileperblock_wincall, \c fileperblock_boostfd : * same as above, but take a single file per block, using full_disk_filename as file name prefix. * Usually provide worse performance than the standard variants, * but release freed blocks to the file system immediately. * - \c memory : keeps all data in RAM, for quicker testing * - \c wbtl : library-based write-combining (good for writing small blocks onto SSDs), * based on \c syscall * * See also the example configuration file \c 'config_example_win' included in the archive. * * * \section excreation Precreating external memory files * * In order to get the maximum performance one should precreate disk files described in the configuration file, * before running \c STXXL applications. * * The precreation utility is included in the set of \c STXXL * utilities ( \c utils\\createdisks.exe ). Run this utility * for each disk you have defined in the disk configuration file: * \verbatim utils\createdisks.exe capacity full_disk_filename... \endverbatim * * */ /*! * \page install-svn Installing from subversion * * \section checkout Retrieving the source from subversion * * The \c STXXL source code is available in a subversion repository on sourceforge.net.
* To learn more about subversion and (command line and graphical) subversion clients * visit http://subversion.tigris.org/. * * The main development line (in subversion called the "trunk") is located at * \c https://stxxl.svn.sourceforge.net/svnroot/stxxl/trunk *
Alternatively you might use a branch where a new feature is being developed. * Branches have URLs like * \c https://stxxl.svn.sourceforge.net/svnroot/stxxl/branches/foobar * * For the following example let us assume you want to download the latest trunk version * using the command line client and store it in a directory called \c stxxl-trunk * (which should not exist, yet). * Otherwise replace URL and path to your needs. * * Run: \verbatim svn checkout https://stxxl.svn.sourceforge.net/svnroot/stxxl/trunk stxxl-trunk \endverbatim * Change to stxxl directory: \verbatim cd stxxl-trunk \endverbatim * * \section svn_continue_installation Continue as Usual * * Now follow the regular installation and usage instructions, * starting from "Library Compilation": * - \ref library_compilation_linux_gcc "Linux/Unix – g++/icpc/clang++" * - \ref library_compilation_msvc "Windows – Microsoft Visual C++" * * \section update Updating an existing subversion checkout * * Once you have checked out the source code you can easily update it to the latest version later on. * * In the STXXL directory, run * \verbatim svn update \endverbatim * and rebuild. * */