14 #ifndef STXXL_IOBASE_HEADER
15 #define STXXL_IOBASE_HEADER
17 #ifdef STXXL_BOOST_CONFIG
18 #include <boost/config.hpp>
21 #if defined (__linux__)
22 #define STXXL_CHECK_BLOCK_ALIGNING
36 #include <sys/types.h>
51 #include <sys/resource.h>
55 #ifdef STXXL_BOOST_THREADS // Use Portable Boost threads
57 #include <boost/thread/thread.hpp>
58 #include <boost/thread/mutex.hpp>
59 #include <boost/bind.hpp>
76 #if defined (__linux__)
78 #if !defined (O_DIRECT) && (defined (__alpha__) || defined (__i386__))
79 #define O_DIRECT 040000
85 #define O_DIRECT O_SYNC
89 #include <stxxl/bits/namespace.h>
90 #include <stxxl/bits/io/iostats.h>
91 #include <stxxl/bits/common/semaphore.h>
92 #include <stxxl/bits/common/mutex.h>
93 #include <stxxl/bits/common/switch.h>
94 #include <stxxl/bits/common/state.h>
95 #include <stxxl/bits/common/exceptions.h>
96 #include <stxxl/bits/io/completion_handler.h>
99 __STXXL_BEGIN_NAMESPACE
106 #define BLOCK_ALIGN 4096
108 typedef void * (*thread_function_t)(
void *);
109 typedef stxxl::int64 DISKID;
126 class file :
private noncopyable
170 virtual void set_size(stxxl::int64 newsize) = 0;
173 virtual stxxl::int64
size() = 0;
175 __STXXL_DEPRECATED(
int get_disk_number())
188 virtual void lock() { }
191 virtual void delete_region(int64 offset, unsigned_type
size)
212 template <
class request_iterator_>
214 request_iterator_
wait_any(request_iterator_ reqs_begin, request_iterator_ reqs_end);
216 friend class disk_queue;
221 virtual bool add_waiter(onoff_switch * sw) = 0;
222 virtual void delete_waiter(onoff_switch * sw) = 0;
224 virtual void serve() = 0;
229 std::auto_ptr<stxxl::io_error> error;
234 enum request_type { READ, WRITE };
259 stxxl::int64 offset_,
261 request_type type_) :
262 on_complete(on_compl), ref_cnt(0),
269 STXXL_VERBOSE3(
"request " << static_cast<void *>(
this) <<
": creation, cnt: " << ref_cnt);
272 virtual void wait() = 0;
275 virtual bool poll() = 0;
284 STXXL_VERBOSE3(
"request " << static_cast<void *>(
this) <<
": deletion, cnt: " << ref_cnt);
286 file * get_file()
const {
return file_; }
287 void * get_buffer()
const {
return buffer; }
288 stxxl::int64 get_offset()
const {
return offset; }
289 size_t get_size()
const {
return bytes; }
290 size_t size()
const {
return bytes; }
291 request_type get_type()
const {
return type; }
293 virtual std::ostream & print(std::ostream & out)
const
295 out <<
"File object address: " << (
void *)get_file();
296 out <<
" Buffer address: " << (
void *)get_buffer();
297 out <<
" File offset: " << get_offset();
298 out <<
" Transfer size: " << get_size() <<
" bytes";
299 out <<
" Type of transfer: " << ((get_type() == READ) ?
"READ" :
"WRITE");
307 error.reset(
new stxxl::io_error(msg));
314 error.reset(
new stxxl::io_error(msg));
321 throw * (error.get());
329 STXXL_VERBOSE3(
"request add_ref() " << static_cast<void *>(
this) <<
": adding reference, cnt: " << ref_cnt);
338 STXXL_VERBOSE3(
"request sub_ref() " << static_cast<void *>(
this) <<
": subtracting reference cnt: " << ref_cnt);
345 inline std::ostream & operator << (std::ostream & out,
const request & req)
347 return req.print(out);
369 STXXL_VERBOSE3(
"the last copy " << static_cast<void *>(ptr) <<
" this=" << static_cast<void *>(
this));
375 STXXL_VERBOSE3(
"more copies " << static_cast<void *>(ptr) <<
" this=" << static_cast<void *>(
this));
384 STXXL_VERBOSE3(
"create constructor (request =" << static_cast<void *>(ptr) <<
") this=" << static_cast<void *>(
this));
390 STXXL_VERBOSE3(
"copy constructor (copying " << static_cast<void *>(ptr) <<
") this=" << static_cast<void *>(
this));
396 STXXL_VERBOSE3(
"Destructor of a request_ptr pointing to " << static_cast<void *>(ptr) <<
" this=" << static_cast<void *>(
this));
404 return (*
this = p.ptr);
410 STXXL_VERBOSE3(
"assign operator begin (assigning " << static_cast<void *>(p) <<
") this=" << static_cast<void *>(
this));
417 STXXL_VERBOSE3(
"assign operator end (assigning " << static_cast<void *>(p) <<
") this=" << static_cast<void *>(
this));
468 for (
int i = 0; i < count; i++)
470 req_array[i]->
wait();
474 template <
class request_iterator_>
475 void wait_all(request_iterator_ reqs_begin, request_iterator_ reqs_end)
477 while (reqs_begin != reqs_end)
487 for (
int i = 0; i < count; i++)
489 if (req_array[i]->poll())
498 template <
class request_iterator_>
499 request_iterator_
poll_any(request_iterator_ reqs_begin, request_iterator_ reqs_end)
501 while (reqs_begin != reqs_end)
514 stats::scoped_wait_timer wait_timer;
517 int i = 0, index = -1;
519 for ( ; i < count; i++)
521 if (req_array[i]->add_waiter(&sw))
527 req_array[i]->delete_waiter(&sw);
537 for (i = 0; i < count; i++)
539 req_array[i]->delete_waiter(&sw);
540 if (index < 0 && req_array[i]->poll())
547 template <
class request_iterator_>
548 request_iterator_
wait_any(request_iterator_ reqs_begin, request_iterator_ reqs_end)
550 stats::scoped_wait_timer wait_timer;
554 request_iterator_ cur = reqs_begin, result = reqs_end;
556 for ( ; cur != reqs_end; cur++)
563 if (cur != reqs_begin)
565 while (--cur != reqs_begin)
579 for (cur = reqs_begin; cur != reqs_end; cur++)
582 if (result == reqs_end && (
request_ptr(*cur))->poll())
589 class disk_queue :
private noncopyable
592 enum priority_op { READ, WRITE, NONE };
597 std::queue<request_ptr> write_queue;
598 std::queue<request_ptr> read_queue;
602 priority_op _priority_op;
604 #ifdef STXXL_BOOST_THREADS
605 boost::thread thread;
611 static void * worker(
void * arg);
614 disk_queue(
int n = 1);
616 void set_priority_op(priority_op op)
629 friend class singleton<disk_queues>;
632 std::map<DISKID, disk_queue *> queues;
638 if (queues.find(disk) == queues.end())
641 queues[disk] =
new disk_queue();
643 queues[disk]->add_readreq(req);
647 if (queues.find(disk) == queues.end())
650 queues[disk] =
new disk_queue();
652 queues[disk]->add_writereq(req);
657 for (std::map<DISKID, disk_queue *>::iterator i =
658 queues.begin(); i != queues.end(); i++)
668 for (std::map<DISKID, disk_queue *>::iterator i =
669 queues.begin(); i != queues.end(); i++)
670 i->second->set_priority_op(op);
676 __STXXL_END_NAMESPACE
678 #endif // !STXXL_IOBASE_HEADER