|
||||
|
8.6 Буферизация При задании операций ввода/вывода мы никак не касались типов файлов, но ведь не все устройства можно рассматривать одинаково с точки зрения стратегии буферизации. Например, для ostream, подключенного к символьной строке, требуется буферзация другого вида, нежели для ostream, подключенного к фалу. С этими пробемами можно справиться, задавая различные бферные типы для разных потоков в момент инициализации (обратите внимание на три конструктора класса ostream). Есть только один набор операций над этими буферными типами, поэтму в функциях ostream нет кода, их различающего. Однако фунции, которые обрабатывают переполнение сверху и снизу, виртальные. Этого достаточно, чтобы справляться с необходимой в данное время стратегией буферизации. Это также служит хорошим примером применения виртуальных функций для того, чтобы сдлать возможной однородную обработку логически эквивалентных средств с различной реализацией. Описание буфера потока в «stream.h» выглядит так: struct streambuf (* // управление буфером потока char* base; // начало буфера char* pptr; // следующий свободный char char* qptr; // следующий заполненный char char* eptr; // один из концов буфера char alloc; // буфер, выделенный с помощью new // Опустошает буфер: // Возвращает EOF при ошибке и 0 в случае успеха virtual int overflow(int c =EOF); // Заполняет буфер // Возвращет EOF при ошибке или конце ввода, // иначе следующий char virtual int underflow(); int snextc() // берет следующий char (* return (++qptr==pptr) ? underflow() : *qptr amp;0377; *) // ... int allocate() //выделяет некоторое пространство буфера streambuf() (* /* ... */*) streambuf(char* p, int l) (* /* ... */*) ~streambuf() (* /* ... */*) *); Обратите внимание, что здесь определяются указатели, нобходимые для работы с буфером, поэтому обычные посимвольные действия можно определить (только один раз) в виде максимално эффективных inlinфункций. Для каждой конкретной стратгии буферизации необходимо определять только функции перепонения overflow() и underflow(). Например: struct filebuf : public streambuf (* int fd; // дескриптор файла char opened; // файл открыт int overflow(int c =EOF); int underflow(); // ... // Открывает файл: // если не срабатывает, то возвращет 0, // в случае успеха возвращает «this» filebuf* open(char *name, open_mode om); int close() (* /* ... */ *) filebuf() (* opened = 0; *) filebuf(int nfd) (* /* ... */ *) filebuf(int nfd, char* p, int l) : (p,l) (* /*...*/ *) ~filebuf() (* close(); *) *); int filebuf::underflow() // заполняет буфер из fd (* if (!opened !! allocate()==EOF) return EOF; int count = read(fd, base, eptr-base); if (count « 1) return EOF; qptr = base; pptr = base + count; return *qptr amp; 0377; *) |
|
||