FBB::SharedStream(3bobcat)

I/O on shared memory
(libbobcat-dev_4.08.03-x.tar.gz)

2005-2018

NAME

FBB::SharedStream - I/O operations on shared memory

SYNOPSIS

#include <bobcat/sharedstream>
Linking option: -lpthread -lbobcat

DESCRIPTION

This class combines the features of the std::istream and std::ostream classes, operating on shared memory. As with std::fstream objects, a seekp or seekg member call is required to switch from writing to reading or v.v.

As with std::fstream objects, FBB::SharedStream objects do not keep separate offsets for reading and writing: the seek-members always refer to the (single) offset maintained by the FBB::SharedMemory object to which the SharedStream object interfaces.

So, although tellg and tellp return identical values, tellg should not be called after writing to a SharedStream object, and tellp should not be called after reading from a SharedStream object, as calling members related to reading (tellg) after writing and v.v. put the stream in its fail state.

NAMESPACE

FBB
All constructors, members, operators and manipulators, mentioned in this man-page, are defined in the namespace FBB.

INHERITS FROM

FBB::SharedStreambuf (private inheritance),
std::istream,
std::ostream,
FBB::SharedEnum__ (cf. sharedmemory(3bobcat) for a description of this base class).

SIZEUNIT ENUMERATION

The enum SizeUnit defines the following symbolic constants:

EXAMPLE

#include <iostream>
#include <string>
#include <ostream>
#include <istream>

#include <bobcat/exception>
#include <bobcat/sharedstream>
#include <bobcat/sharedcondition>

using namespace std;
using namespace FBB;

int main()
{
    SharedStream sharedStream;

    int id = -1;

    while (true)
    {
        cout << 
                "\n"
                " K             kill (no lock) existing shared segment\n"
                " S             show stats of current shared segment\n"
                " L <id>        Load segment <id>\n"
                " C             Install a SharedCondition at offset 0\n"
                " c            create new shared memory (sets id)\n"
//                " l            lock segment id until key pressed\n"
//                " p <x> c      put char c at offset x\n"
                " q            quit\n"
//                " r <x> <n>    read n chars from offset x\n"
//                " w <x> args   write all args at offset x\n"
                  " i            insert lines (until empty) at the current "
                                                                "offset\n"

                  " x            extract lines (until EOF) from the current "
                                                                "offset\n"
                  " X            extract the next line from the current "
                                                                "offset\n"
                  "              when nodified via 'N'\n"
                  " N            notify a waiting X\n"
                  " s <x>        seek (abs) offset x\n"
                "? ";

        char ch;
        cin >> ch;

        ios::off_type offset;

        cout << "Requested: " << ch << '\n';

        sharedStream.clear();

        switch (ch)
        {
            case 'c':
            {
                sharedStream.open(1, SharedStream::kB);

                id = sharedStream.id();
                cout << "id = " << id << '\n';
                sharedStream.memInfo(cout);
                cout << '\n';
            }
            break;
        
            case 'C':
            {
                sharedStream.seekp(0);
                SharedCondition cond(sharedStream.createSharedCondition());
                sharedStream.seekg(cond.width());
                break;
            }

            case 'K':         // delete segment
            {
                if (id == -1)
                {
                    cout << "No segment loaded\n";
                    continue;
                }

                cout << "Removing segment id = " << id << '\n';
                if (ch == 'R')
                    sharedStream.remove();
                else
                    sharedStream.kill();

                id = -1;
            }
            break;

            case 'L':
                cin >> id;
                cout << "Loading segment " << id << '\n';
                sharedStream.open(id);
                sharedStream.memInfo(cout);
                cout << '\n';
            break;

            case 'S':
                if (id == -1)
                {
                    cout << "No segment loaded\n";
                    continue;
                }
                sharedStream.memInfo(cout);
                cout << '\n';
            break;
            
            case 's':
            {
                size_t offset;
                if (id == -1)
                {
                    cout << "No segment loaded\n";
                    continue;
                }
                cin >> offset;
                sharedStream.seekg(offset);
                sharedStream.seekp(offset);
                cout << "tellg: " << sharedStream.tellg() << ", "
                        "tellp: " << sharedStream.tellp() << '\n';
            }
            break;
            
            case 'i':
            {
                string line;
                getline(cin, line);
                sharedStream.seekp(0, ios::cur);
                while (true)
                {
                    cout << "? ";
                    if (not getline(cin, line) || line.empty())
                        break;
                    sharedStream << line << endl;
                    cout << 
                            "   tellp: " << sharedStream.tellp() << '\n';
                }
                    cout << // "   tellg: " << sharedStream.tellg() << ", "
                            "   tellp: " << sharedStream.tellp() << '\n';
            }
            break;
                    
            case 'x':
            {
                string line;
                sharedStream.seekg(0, ios::cur);

                while (true)
                {
                    cout << ": ";
                    if (not getline(sharedStream, line))
                        break;
                    cout << line << "\n"
                            "   tellg: " << sharedStream.tellg() << ", "
                            "   tellp: " << sharedStream.tellp() << '\n';
                }
            }
            break;
                    
            case 'X':
            {
                SharedCondition cond(sharedStream.attachSharedCondition(0));

                string line;
                sharedStream.seekg(cond.width());

                cond.lock();

                while (true)
                {
                    cond.wait();

                    cout << ": ";
                    if (not getline(sharedStream, line))
                        break;

                    cout << line << "\n"
                            "   tellg: " << sharedStream.tellg() << ", "
                            "   tellp: " << sharedStream.tellp() << '\n';
                }
                cout << "All done\n";
                cond.unlock();
            }
            break;

            case 'N':
            {
                string line;
                getline(cin, line);

                SharedCondition cond(sharedStream.attachSharedCondition(0));
                while (true)
                {
                    cout << "'enter' or 'q'? ";
                    getline(cin, line);

                    if (line == "q")
                        break;

                    cond.lock();
                    cond.notify();
                    cond.unlock();
                }
            }
            break;
        
            case 'p':           // put a char behind the last written
            {
                if (id == -1)
                {
                    cout << "No segment loaded\n";
                    continue;
                }

                cin >> offset >> ch;
                if (!cin)
                    throw Exception() << "cmd specification error";
    
                sharedStream.seekp(offset);
                cout << "Segment id = " << id << " at write offset " << 
                                                    sharedStream.tellp() << '\n';
                sharedStream.put(ch);
            }
            break;
                
            case 'r':           // put a char behind the last written
            {
                if (id == -1)
                {
                    cout << "No segment loaded\n";
                    continue;
                }

                int n;

                cin >> offset >> n;
                if (!cin)
                    throw Exception() << "cmd specification error";

                char buf[n];

                sharedStream.seekg(offset);
                cout << "Segment id = " << id << " at offset " << 
                         sharedStream.tellg() << ", to read " << n << " bytes\n";
    
                n = sharedStream.read(buf, n).gcount();
    
                if (n < 0)
                    cout << "No data at " << offset << '\n';
                else
                {
                    cout << "Retrieved " << n << " bytes, containing `";
                    cout.write(buf, n);
                    cout << "'\n";
    
                    for (auto ch: buf)
                        cout << static_cast<int>(ch) << ' ';
                    cout << '\n';
                }
            }
            break;
                
            case 'w':           // write chars at offset
            {
                if (id == -1)
                {
                    cout << "No segment loaded\n";
                    continue;
                }

                string line;

                cin >> offset;
                getline(cin, line);
                if (!cin)
                    throw Exception() << "cmd specification error";
    
                streampos pos = sharedStream.seekp(offset).tellp();

                cout << "Segment id = " << id << " at offset " << 
                         pos << ", to write " << line.length() << " bytes\n";
    
                
                sharedStream.write(line.data(), line.length());

                if (!sharedStream)
                    cout << "No room left to write any bytes\n";
                else
                    cout << "Wrote " << (sharedStream.tellp() - pos) << " bytes\n";
            }
            break;
                
            case 'q':
            return 0;

            default:
                cout << "request not implemented: " << ch << '\n';
            break;
        }
    }
}

FILES

bobcat/sharedstream - defines the class interface

SEE ALSO

bobcat(7), chmod(1), isharedstream(3bobcat), osharedstream(3bobcat), sharedblock(3bobcat), sharedcondition(3bobcat), sharedmemory(3bobcat) sharedmutex(3bobcat), sharedpos(3bobcat), sharedsegment(3bobcat), sharedstreambuf(3bobcat)

BUGS

Note that by default exceptions thrown from within a std::stream object are caught by the stream object, setting its ios::failbit flag. To allow exceptions to leave a stream object, its exceptions member can be called, e.g., using:

    myStream.exceptions(ios::failbit | ios::badbit | ios::eofbit);
        

DISTRIBUTION FILES

BOBCAT

Bobcat is an acronym of `Brokken's Own Base Classes And Templates'.

COPYRIGHT

This is free software, distributed under the terms of the GNU General Public License (GPL).

AUTHOR

Frank B. Brokken (f.b.brokken@rug.nl).