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.
The enum SizeUnit defines the following symbolic constants:
By default, the shared memory segment is opened for reading and writing. Different from the open modes used for file streams, creating a shared memory stream with open modes ios::in | ios::out is OK. In this case the shared memory segment is created and once information has been written to the shared memory it can also be read again.
The shared memory's access rights are defined by the access parameter, interpreted as an octal value, using the well-known (chmod(1)) way to define the access rights for owner, group and others.
If construction fails, an FBB::Exception is thrown.
Specifying the ios::trunc flag immediately clears the contents of the shared memory.
An FBB::Exception is thrown if construction fails (e.g., no shared memory segment having ID id exists),
No overloaded move and copy assignment operators are available.
All members of std::istream and std::ostream and the enum values kB, MB, and GB, defined by FBB::SharedEnum__ are available.
An FBB::Exception is thrown if the FBB::SharedCondition object could not be constructed.
An FBB::Exception is thrown if the FBB::SharedCondition object could not be constructed.
By default, the shared memory segment is opened for reading and writing. Different from the open modes used for file streams, creating a shared memory stream with open modes ios::in | ios::out is OK. In this case the shared memory segment is created and once information has been written to the shared memory it can also be read again.
The shared memory's access rights are defined by the access parameter, interpreted as an octal value, using the well-known (chmod(1)) way to define the access rights for owner, group and others.
If opening fails, an FBB::Exception is thrown.
Specifying the ios::trunc flag immediately clears the contents of the shared memory.
An FBB::Exception is thrown if opening fails (e.g., no shared memory segment having ID id exists).
#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; } } }
myStream.exceptions(ios::failbit | ios::badbit | ios::eofbit);