boost :: iostreams erőforrás-gazdálkodás

szavazat
1

Új vagyok, hogy növeljék és iostreams csomagot, és találd meg a dokumentációt egy kicsit sovány. Remélhetőleg valaki engem egyenes. Próbálom átalakítani egy kis darab C # patakok kódot írtam egy kicsit vissza az olvasás egy tömörített adatfolyamot.

byte[] data = new byte[length - 1];
file.Read(data, 0, data.Length);

Stream ret = new ZlibStream(new MemoryStream(data), CompressionMode.Decompress, true);
return ret;

Az adatok egy részét fájl beolvasása egy memória puffer, amely táplálja a zlib kicsomagoló. A fogyasztó a patak felveszi el rajta az idő múlásával, és amikor kész, akkor hívjon Close(), amelyek együtt a szemétgyűjtő tisztítsák meg a rendelkezésre álló erőforrásokat. Megjegyzés : fontos különbséget nem akarok kibontani a teljes fájl, csak egy kis része az egyik. A fájl már törekszenek, néhány belső helye és hossza képest kicsi a teljes méretű a fájl.

Próbálom felér a legjobb egyenértékűek ezen a C ++ kódot Boost. Eddig ez az erkölcsi egyenértékű a fent (nem tesztelt):

char * data = new char[length - 1];
_file.read(data, length - 1);

io::stream_buffer<io::basic_array_source<char> > buffer(data, length - 1);

io::filtering_stream<io::input> * in = new io::filtering_stream<io::input>;         
in->push(io::zlib_decompressor());
in->push(buffer);

return in;

Gondolom én is vissza a filtering_stream csomagolva egy shared_ptr, ami megment a fogyasztót, hogy aggódnia törlése a patak, de azt is, hogy az adatok puffer new'd fel ott. Ideális esetben szeretnék a fogyasztó csak hívja close()a patak és néhány mechanizmus (pl callback) lenne megtisztítani a mögöttes erőforrások a szűrőt. Kötelezve a fogyasztót, hogy adja át a folyam explicit kiadás funkció is elfogadható, de még mindig nem vagyok teljesen biztos benne, hogyan lehet az alapul szolgáló adatok puffer vissza az első helyen.

Tisztább alternatív megoldások is fogadunk.

Update 1

Megpróbáltam lazán megragadva a megjegyzésre Cat Plus Plus egy std :: vector által támogatott pilóta. Ez nem elég, amit tettem, de ez az, amit én már felér eddig. Az alábbi kódot, van egy boost :: shared_array támogatott pilóta alapján a boost vezető példák.

namespace io = boost::iostreams;

class shared_array_source
{
public:

    typedef char            char_type;
    typedef io::source_tag  category;

    shared_array_source (boost::shared_array<char> s, std::streamsize n)
        : _data(s), _pos(0), _len(n)
    { }

    std::streamsize read (char * s, std::streamsize n)
    {
        std::streamsize amt = _len - _pos;
        std::streamsize result = (std::min)(amt, n);

        if (result != 0) {
            std::copy(_data.get() + _pos, _data.get() + _pos + result, s);
            return result;
        }
        else {
            return -1;
        }
    }

private:
    boost::shared_array<char> _data;
    std::streamsize _pos;
    std::streamsize _len;
};

Aztán ott van a függvény, amely visszaadja a patak

io::filtering_istream * GetInputStream (...)
{
    // ... manipulations on _file, etc.

    boost::shared_array<char> data(new char[length - 1]);
    _file.read(data.get(), length - 1);

    shared_array_source src(data, length - 1);
    io::stream<shared_array_source> buffer(src);

    io::filtering_istream * in = new io::filtering_istream;
    in->push(io::zlib_decompressor());
    in->push(buffer);

    // Exhibit A
    // uint32_t ui;
    // rstr->read((char *)&ui, 4);

    return in;
}

És a fő funkciója a vizsgálati program:

int main () {
    boost::iostreams::filtering_istream * istr = GetInputStream();

    // Exhibit B
    uint32_t ui;
    rstr->read((char *)&ui, 4);

    return 0;
}

Figyelmen kívül hagyja azt a tényt, hogy még visszatérek egy mutatót, amely soha nem szabadul - Megtartom ezt a lehető legegyszerűbb. Mi történik, amikor futtatni ezt? Ha megjegyzésből a kódot mutatnak, kapok egy megfelelő jelet ad ui. De amikor elütöttem kiállítás B, I összeomlik mély, mély, mélyen a kiemelés (néha). Nos szar, kimentem a körét és a dolgok tört, néhány helyi kell dekonstruáló és Messiás mindent. datavan egy shared_array, invan a halom, és a kompresszor úgy van kialakítva szerinti docs.

Az egyik a boost konstruktőrök vagy funkciók rángatás hivatkozás egy tárgyat a verem (azaz io :: patak vagy filtering_stream push)? Ha ez a helyzet, én vagyok a fajta tér vissza az egyik unmananaged tárgyakat a kupac.

A kérdést 12/06/2011 13:57
a forrás felhasználó
Más nyelveken...                            


2 válasz

szavazat
1

Tényleg kell elkerülni azon semmit a kupac. filtering_streamlehet tömörítse on the fly, így nem kell cserélni a puffer, vagy olvassa el a fájl tartalmát először. A kódot a következőképpen néz ki:

io::filtering_stream stream;
stream.push(io::zlib_decompressor());
stream.push(_file);

Ha tényleg kell kiosztani azt a kupac, akkor igen, akkor csavarja be egy okos mutató (de megint nem olvasható a fájl adatait az első - és te kockáztatva a szivárgás, hogy az átmeneti, nem is beszélve olvasása nagy fájl így lehet rettenetesen hatékony).

Válaszolt 12/06/2011 14:09
a forrás felhasználó

szavazat
0

Végül kellett lemondani próbál Növelje iostreams megtisztítása után magukat. Bár ami egyéni tömbeszköz hogy belsőleg használt boost :: shared_array megoldotta a problémát az adataim ütközőt marad a kupac, kiderül, hogy boost :: iostreams :: filtering_stream / streambuf hogy egy hivatkozás egy tárgy szorult a lánc , ami azt jelenti, hogy volt elfog egy hivatkozást a készüléken a verem (amennyire tudtam következtetni a forrás és a viselkedés, egyébként). Tudtam új és korszerű eszköz a kupac, de ez csak hozza vissza tér egy.

Saját következő megoldás mozog létrehozását a folyamot egy vékony std :: istream_FAR borítás, amit aztán vissza kell belsejében egy boost :: shared_ptr, amely lehetővé teszi az összes erőforrás kell takarítani, amikor az utolsó referencia megsemmisül.

template <class Compressor>
class CompressedIStream : public std::basic_istream<char, std::char_traits<char> >
{
public:
    CompressedIStream (std::istream& source, std::streamsize count)
        : _data(new char[count]), _buffer(_data, count), std::basic_istream<char, std::char_traits<char> >(&_filter)
    {
        source.read(_data, count);

        _filter.push(Compressor());
        _filter.push(_buffer);
    }

    virtual ~CompressedIStream ()
    {
        delete[] _data;
    }

private:
    char * _data;
    io::stream_buffer<io::basic_array_source<char> > _buffer;
    io::filtering_istreambuf _filter;
};

boost::shared_ptr<std::istream> GetInputStream (...)
{
    // ... manipulations on _file, etc.

    typedef CompressedIStream<io::zlib_decompressor> StreamType;
    return boost::shared_ptr<StreamType>(new StreamType(_file, length - 1));
}
Válaszolt 14/06/2011 02:51
a forrás felhasználó

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more