Связь и интернет Архив Программирование
   
Сделать стартовойСделать закладку            
   ПОИСК  
   
Главная / C / C++ / Введение в язык C++ / Потоки /
8  Perl
8  PHP
8  JavaScript
8  HTML
8  DHTML
8  XML
8  CSS
8  C / C++
8  Pascal и Delphi
8  Турбо Ассемблер
8  MySQL
8  CASE-технологии
8  Алгоритмы
8  Python
8  Обратная связь
8  Гостевая книга
Новости о мире


Буферизация - Программирование от RIN.RU
Буферизация

При задании операций ввода/вывода мы никак не касались типов файлов, но ведь не все устройства можно рассматривать одинаково с точки зрения стратегии буферизации. Например, для ostream, подключенного к символьной строке, требуется буферизация другого вида, нежели для ostream, подключенного к файлу. С этими проблемами можно справиться, задавая различные буферные типы для разных потоков в момент инициализации (обратите внимание на три конструктора класса ostream). Есть только один набор операций над этими буферными типами, поэтому в функциях ostream нет кода, их различающего. Однако функции, которые обрабатывают переполнение сверху и снизу, виртуальные. Этого достаточно, чтобы справляться с необходимой в данное время стратегией буферизации. Это также служит хорошим примером применения виртуальных функций для того, чтобы сделать возможной однородную обработку логически эквивалентных средств с различной реализацией. Описание буфера потока в выглядит так:


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&0377;
}
 
 
// ...
 
 
int allocate() // выделяет некоторое пространство буфера
 
 
streambuf() { /* ... */}
streambuf(char* p, int l) { /* ... */}
~streambuf() { /* ... */}
};


Обратите внимание, что здесь определяются указатели, необходимые для работы с буфером, поэтому обычные посимвольные действия можно определить (только один раз) в виде максимально эффективных inline- функций. Для каждой конкретной стратегии буферизации необходимо определять только функции переполнения 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 & 0377;
}




 8  Комментарии к статье  8 8  Обсудить в чате

8  В тему

Потоки

Введение

Вывод

Файлы и Потоки

Ввод

Работа со Строками

Эффективность

 
  
  
    Copyright ©  RIN 2003 - 2004      * Обратная связь