Используйте несколько потоков для записи в один выходной файл в C++

У меня урок Writer это имеет два ofstream члены.
Оба потока связаны с одним и тем же выходным файлом. Я хотел бы использовать оба потока в Writer::write метод, но чтобы убедиться, что каждый поток записывает в конец реального выходного файла.

Код

class my_ofstream1:
    public ofstream
{
    // implement some functions.
    // using internal, extended type of streambuf
};

class my_ofstream2:
    public ofstream
{
    // implement some functions.
    // using internal, extended type of streambuf 
    // (not the same type as found in my_ofstream1)
};


class Writer
{
public:

    void open(string path)
    {
        f1.open(path.c_str(),ios_base::out); f2.open(path.c_str(),ios_base::out);
    }

    void close()
    {
        f1.close(); f2.close();
    }

    void write()
    {
        string s1 = "some string 1";
        string s2 = "some string 2";
        f1.write(s1.c_str(), s1.size());

        // TBD - ensure stream f2 writes to the end of the actual output file
        assert(f1.tellp() == f2.tellp());
        f2.write(s2.c_str(), s2.size());
    }

private:
    my_ofstream1 f1;
    my_ofstream1 f2;
};

void main()
{
    Writer w;
    w.open("some_file.txt");
    w.write();
    w.close();
}

Вопросы

Как обеспечить f2 синхронизирован с f1? это означает, что перед записью смещение потока f2 должен быть синхронизирован со смещением потока f1 и наоборот?
Я не могу использовать функцию std::ios::rdbuf, так как каждый ofstream использует специальные производные streambuf, так с помощью rdbuf() Я потеряю необходимый функционал.
Я попытался использовать некоторые методы, описанные в разделе " Синхронизация потоков", но не смог этого сделать.

2 ответа

Решение

Похоже, что оба ваших класса используют идиому фильтрации streambuf. В любом случае, не выводите свои уроки из std::ofstream, но прямо из ostreamи пусть они оба используют одно и то же std::filebuf объект. Если вы используете идиому фильтрации streambuf, не позволяйте буферизировать ваш streambuf фильтрации; оставить это до финала std::filebuf,

Другими словами, ваш "внутренний расширенный тип streambuf" должен содержать указатель на конечный приемник, который будет filebuf (но ваши фильтрующие потоковые буферы не должны знать это). Функции как syncони просто передаются в конечный пункт назначения, и им никогда не следует устанавливать буфер самостоятельно, а передавать все в filebuf.

Разве это не то, что вы ищете? Это может быть легко модифицировано для работы с ostream, а не с ofstream, что лучше - актуальная проблема - синхронизация буферов. В этом коде я просто сделал filebuf bf небуферизованный и работает нормально. Или оставьте его в буфере, но включите звонки pubsync при переключении между my_ofstream's. Я не понимаю почему ios:rdbuf не доступен. Вы создаете свой собственный streambuf?

#include <iostream>
#include <fstream>
#include <assert.h>

using namespace std;

class my_ofstream1 : public ofstream
{
public:
    my_ofstream1& write (const char_type* s, streamsize n)
    {
        ofstream::write (s, n);
        //rdbuf()->pubsync();
        return *this;
    }

    void attach (filebuf* bf){
        ios::rdbuf(bf);
    }
};

class my_ofstream2 : public ofstream
{
public:
    my_ofstream2& write (const char_type* s, streamsize n)
    {
        ofstream::write (s, n);
        //rdbuf()->pubsync();
        return *this;
    }

    void attach (filebuf* bf){
        ios::rdbuf(bf);
    }
};


class Writer
{
    filebuf bf;
    my_ofstream1 f1;
    my_ofstream1 f2;

public:

    void open(string path)
    {
        bf.open(path.c_str(),ios_base::out);
        bf.pubsetbuf(0,0); //unbufferred
        f1.attach(&bf); f2.attach(&bf);
    }

    void close()
    {
        f1.close(); f2.close();
    }

    void write()
    {
        string s1 = "some string 1";
        string s2 = "some string 2";
        f1.write(s1.c_str(), s1.size());

        assert(f1.tellp() == f2.tellp());
        f2.write(s2.c_str(), s2.size());
    }


};

int main()
{
    Writer w;
    w.open("some_file.txt");
    w.write();
    w.close();

    return 0;
}   
Другие вопросы по тегам