updated io stream, simplified interface, faster cin

This commit is contained in:
Daniel Larimer 2012-10-26 00:58:29 -04:00
parent 4aad422411
commit c123fb39c2
4 changed files with 239 additions and 84 deletions

View file

@ -12,25 +12,7 @@ namespace fc {
virtual size_t readsome( char* buf, size_t len ) = 0;
virtual istream& read( char* buf, size_t len ) = 0;
template<typename T>
friend istream& operator>>( istream& i, T& v ){ return i.read(v); }
virtual bool eof()const = 0;
protected:
virtual istream& read( int64_t& ) = 0;
virtual istream& read( uint64_t& ) = 0;
virtual istream& read( int32_t& ) = 0;
virtual istream& read( uint32_t& ) = 0;
virtual istream& read( int16_t& ) = 0;
virtual istream& read( uint16_t& ) = 0;
virtual istream& read( int8_t& ) = 0;
virtual istream& read( uint8_t& ) = 0;
virtual istream& read( float& ) = 0;
virtual istream& read( double& ) = 0;
virtual istream& read( bool& ) = 0;
virtual istream& read( char& ) = 0;
virtual istream& read( fc::string& ) = 0;
};
class ostream {
@ -38,18 +20,10 @@ namespace fc {
virtual ~ostream(){};
virtual ostream& write( const char* buf, size_t len ) = 0;
virtual void close() = 0;
virtual void flush() = 0;
template<typename T>
friend ostream& operator<<( ostream& o, const T& v ) { return o.write(fc::lexical_cast<fc::string>(v)); }
friend ostream& operator<<( ostream& o, char* v ) { return o.write(v); }
friend ostream& operator<<( ostream& o, const char* v ) { return o.write(v); }
friend ostream& operator<<( ostream& o, const fc::string& v ){ return o.write(v); }
protected:
virtual ostream& write( const fc::string& ) = 0;
virtual void close(){}
virtual void flush(){}
};
class iostream : public virtual ostream, public virtual istream {};
@ -73,26 +47,42 @@ namespace fc {
virtual size_t readsome( char* buf, size_t len );
virtual istream& read( char* buf, size_t len );
virtual bool eof()const;
virtual istream& read( int64_t& );
virtual istream& read( uint64_t& );
virtual istream& read( int32_t& );
virtual istream& read( uint32_t& );
virtual istream& read( int16_t& );
virtual istream& read( uint16_t& );
virtual istream& read( int8_t& );
virtual istream& read( uint8_t& );
virtual istream& read( float& );
virtual istream& read( double& );
virtual istream& read( bool& );
virtual istream& read( char& );
virtual istream& read( fc::string& );
};
fc::istream& getline( fc::istream&, fc::string&, char delim = '\n' );
fc::cin_t& getline( fc::cin_t&, fc::string&, char delim = '\n' );
extern cout_t cout;
extern cerr_t cerr;
extern cin_t cin;
template<typename T>
ostream& operator<<( ostream& o, const T& v ) {
auto str = fc::lexical_cast<fc::string>(v);
o.write( str.c_str(), str.size() );
return o;
}
ostream& operator<<( ostream& o, const char* v );
template<typename T>
ostream& operator<<( ostream& o, const fc::string& str ) {
o.write( str.c_str(), str.size() );
return o;
}
template<typename T>
istream& operator>>( istream& o, T& v ) {
fc::string str;
getline( o, str, ' ' );
v = fc::lexical_cast<T>(str);
return o;
}
fc::cin_t& getline( fc::cin_t&, fc::string&, char delim = '\n' );
template<typename T>
cin_t& operator>>( cin_t& o, T& v ) {
fc::string str;
getline( o, str, ' ' );
v = fc::lexical_cast<T>(str);
return o;
}
}

View file

@ -0,0 +1,109 @@
#pragma once
#include <fc/iostream.hpp>
#include <fc/shared_ptr.hpp>
namespace fc {
/**
* Used to wrap references to other streams
*/
class ostream_wrapper : public ostream {
public:
template<typename Stream>
ostream_wrapper( Stream& s )
:my( new impl<Stream>(s) ){}
virtual ~ostream_wrapper(){};
virtual ostream& write( const char* buf, size_t len ) {
my->write(buf,len);
return *this;
}
virtual void close() {
my->close();
}
virtual void flush() {
my->flush();
}
protected:
virtual ostream& write( const fc::string& s ) {
return write( s.c_str(), s.size() );
}
struct impl_base : public fc::retainable {
virtual void write( const char* buf, size_t len ) = 0;
virtual void close() = 0;
virtual void flush() = 0;
};
template<typename T>
struct impl : public impl_base {
impl(T& i):st(i){}
virtual void write( const char* buf, size_t len ) {
st.write(buf,len);
}
virtual void close() { st.close(); }
virtual void flush() { st.flush(); }
T& st;
};
fc::shared_ptr<impl_base> my;
};
/**
* Used to wrap references to other streams
*/
class istream_wrapper : public istream {
public:
template<typename Stream>
istream_wrapper( Stream& s )
:my( new impl<Stream>(s) ){}
virtual ~istream_wrapper(){};
virtual size_t readsome( char* buf, size_t len ) { return my->readsome(buf,len); }
virtual istream& read( char* buf, size_t len ) {
my->read(buf,len);
return *this;
}
virtual void close() { }
virtual bool eof()const{ return my->eof(); }
virtual istream& read( int64_t& ) { return *this; }
virtual istream& read( uint64_t& ) { return *this; }
virtual istream& read( int32_t& ) { return *this; }
virtual istream& read( uint32_t& ) { return *this; }
virtual istream& read( int16_t& ) { return *this; }
virtual istream& read( uint16_t& ) { return *this; }
virtual istream& read( int8_t& ) { return *this; }
virtual istream& read( uint8_t& ) { return *this; }
virtual istream& read( float& ) { return *this; }
virtual istream& read( double& ) { return *this; }
virtual istream& read( bool& ) { return *this; }
virtual istream& read( char& ) { return *this; }
virtual istream& read( fc::string& ) { return *this; }
protected:
struct impl_base : public fc::retainable {
virtual void read( char* buf, size_t len ) = 0;
virtual size_t readsome( char* buf, size_t len ) = 0;
virtual bool eof()const;
};
template<typename T>
struct impl : public impl_base {
impl(T& i):st(i){}
virtual size_t readsome( char* buf, size_t len ) { return st.readsome(buf,len); }
virtual void read( char* buf, size_t len ) {
st.read(buf,len);
}
virtual bool eof()const { return st.eof(); }
T& st;
};
fc::shared_ptr<impl_base> my;
};
} // namespace fc

View file

@ -28,6 +28,8 @@ namespace fc {
fc::string to_string( int16_t d );
fc::string to_string( int8_t d );
fc::string to_string( char d );
fc::string to_string( const char* d );
inline fc::string to_string( fc::string s ) { return s; }
template<typename R>
struct lexical_cast<double, R> {

View file

@ -2,28 +2,65 @@
#include <fc/sstream.hpp>
#include <fc/thread.hpp>
#include <iostream>
#include <string.h>
#include <fc/log.hpp>
namespace fc {
fc::thread& cin_thread() { static fc::thread i("cin"); return i; }
fc::cin_t& getline( fc::cin_t& i, fc::string& s, char delim ) {
if( !cin_thread().is_current() ) {
cin_thread().async([&](){ getline(i,s,delim); } ).wait();
return i;
}
fc::stringstream ss;
char c;
i.read( &c, 1 );
while( !i.eof() ) {
if( c == delim ) { s = ss.str(); return i; }
ss.write(&c,1);
i.read( &c, 1 );
}
s = ss.str();
return i;
ostream& operator<<( ostream& o, const char* v ) {
o.write( v, strlen(v) );
return o;
}
struct cin_buffer {
cin_buffer():eof(false),write_pos(0),read_pos(0),cinthread("cin"){
cinthread.async( [=](){read();} );
}
void read() {
char c;
std::cin.read(&c,1);
while( !std::cin.eof() ) {
while( write_pos - read_pos > 0xfffff ) {
fc::promise<void>::ptr wr( new fc::promise<void>() );
write_ready = wr;
if( write_pos - read_pos <= 0xfffff ) {
wr->wait();
}
write_ready.reset();
}
buf[write_pos&0xfffff] = c;
++write_pos;
auto tmp = read_ready; // copy read_ready because it is accessed from multiple threads
if( tmp && !tmp->ready() ) {
tmp->set_value();
}
std::cin.read(&c,1);
}
eof = true;
auto tmp = read_ready; // copy read_ready because it is accessed from multiple threads
if( tmp && !tmp->ready() ) {
tmp->set_value();
}
}
fc::promise<void>::ptr read_ready;
fc::promise<void>::ptr write_ready;
volatile bool eof;
volatile uint64_t write_pos;
char buf[0xfffff+1]; // 1 mb buffer
volatile uint64_t read_pos;
fc::thread cinthread;
};
cin_buffer& get_cin_buffer() {
static cin_buffer* b = new cin_buffer();
return *b;
}
fc::thread& cin_thread() { static fc::thread i("cin"); return i; }
fc::istream& getline( fc::istream& i, fc::string& s, char delim ) {
fc::stringstream ss;
@ -52,32 +89,49 @@ namespace fc {
ostream& cerr_t::write( const fc::string& s ) { std::cerr<< *reinterpret_cast<const std::string*>(&s); return *this; }
size_t cin_t::readsome( char* buf, size_t len ) {
return std::cin.readsome(buf,len);
}
istream& cin_t::read( char* buf, size_t len ) {
if( !cin_thread().is_current() ) {
cin_thread().async( [=](){ this->read(buf,len); } ).wait();
return *this;
cin_buffer& b = get_cin_buffer();
size_t avail = b.write_pos - b.read_pos;
avail = (fc::min)(len,avail);
size_t u = 0;
while( avail && len ) {
*buf = b.buf[b.read_pos&0xfffff];
++b.read_pos;
++buf;
--avail;
--len;
++u;
}
std::cin.read(buf,len);
return u;
}
istream& cin_t::read( char* buf, size_t len ) {
cin_buffer& b = get_cin_buffer();
do {
while( !b.eof && (b.write_pos - b.read_pos)==0 ){
// wait for more...
fc::promise<void>::ptr rr( new fc::promise<void>() );
b.read_ready = rr;
if( b.write_pos - b.read_pos == 0 ) {
rr->wait();
}
b.read_ready.reset();
}
if( b.eof ) return *this;
size_t r = readsome( buf, len );
buf += r;
len -= r;
auto tmp = b.write_ready; // copy write_writey because it is accessed from multiple thwrites
if( tmp && !tmp->ready() ) {
tmp->set_value();
}
} while( len > 0 && !b.eof );
return *this;
}
bool cin_t::eof()const { return std::cin.eof(); }
istream& cin_t::read( int64_t& v) { slog(""); std::cin >> v; return *this; }
istream& cin_t::read( uint64_t& v) { slog(""); std::cin >> v; return *this; }
istream& cin_t::read( int32_t& v) { slog(""); std::cin >> v; return *this; }
istream& cin_t::read( uint32_t& v) { slog(""); std::cin >> v; return *this; }
istream& cin_t::read( int16_t& v) { slog(""); std::cin >> v; return *this; }
istream& cin_t::read( uint16_t& v) { slog(""); std::cin >> v; return *this; }
istream& cin_t::read( int8_t& v) { slog(""); std::cin >> v; return *this; }
istream& cin_t::read( uint8_t& v) { slog(""); std::cin >> v; return *this; }
istream& cin_t::read( float& v) { slog(""); std::cin >> v; return *this; }
istream& cin_t::read( double& v) { slog(""); std::cin >> v; return *this; }
istream& cin_t::read( bool& v) { slog(""); std::cin >> v; return *this; }
istream& cin_t::read( char& v) { slog(""); std::cin >> v; return *this; }
istream& cin_t::read( fc::string& v) { slog(""); std::cin >> *reinterpret_cast<std::string*>(&v); return *this; }
bool cin_t::eof()const { return get_cin_buffer().eof; }
cout_t cout;
cerr_t cerr;