fix cin crash

This commit is contained in:
Daniel Larimer 2012-12-18 14:08:40 -05:00
parent 274146229e
commit afbbf4e8db
8 changed files with 63 additions and 22 deletions

View file

@ -51,8 +51,7 @@ set( sources
src/url.cpp
src/process.cpp
src/http_connection.cpp
src/url.cpp
# src/http_server.cpp
src/http_server.cpp
src/json_rpc_connection.cpp
src/json_rpc_stream_connection.cpp
src/json_rpc_tcp_connection.cpp

View file

@ -44,6 +44,7 @@ namespace fc {
};
struct cin_t : virtual public istream {
~cin_t();
virtual size_t readsome( char* buf, size_t len );
virtual istream& read( char* buf, size_t len );
virtual bool eof()const;

View file

@ -1,5 +1,4 @@
#ifndef FC_MUTEX_HPP_
#define FC_MUTEX_HPP_
#pragma once
#include <fc/time.hpp>
#include <fc/spin_yield_lock.hpp>
@ -107,4 +106,3 @@ namespace fc {
} // namespace fc
#endif // MACE_CMT_MUTEX_HPP_

View file

@ -0,0 +1,11 @@
#pragma once
namespace fc {
template<typename T>
class scoped_lock {
public:
scoped_lock( T& l ):_lock(l) { _lock.lock(); }
~scoped_lock() { _lock.unlock(); }
T& _lock;
};
}

View file

@ -28,11 +28,11 @@ namespace fc {
template<typename Other>
shared_ptr( const shared_ptr<Other>& o )
:_ptr(o.get()) {
if(_ptr) _ptr->retain();
if(_ptr != nullptr ) _ptr->retain();
}
shared_ptr( T* t, bool inc = false )
:_ptr(t) { if( inc ) t->retain(); }
:_ptr(t) { if( inc && t != nullptr) t->retain(); }
shared_ptr():_ptr(nullptr){}
@ -42,25 +42,27 @@ namespace fc {
}
shared_ptr( shared_ptr& p ) {
_ptr = p._ptr;
if( _ptr ) _ptr->retain();
if( _ptr != nullptr ) _ptr->retain();
}
shared_ptr( shared_ptr&& p ) {
_ptr = p._ptr;
p._ptr = nullptr;
}
~shared_ptr() { if( _ptr ) { _ptr->release(); } }
~shared_ptr() { if( nullptr != _ptr ) { _ptr->release(); } }
shared_ptr& reset( T* v = 0, bool inc = false ) {
shared_ptr& reset( T* v = nullptr, bool inc = false ) {
if( v == _ptr ) return *this;
if( _ptr ) _ptr->release();
if( inc && nullptr != v ) v->retain();
if( nullptr != _ptr ) _ptr->release();
_ptr = v;
if( _ptr && inc ) _ptr->retain();
return *this;
}
shared_ptr& operator=(const shared_ptr& p ) {
shared_ptr tmp(p);
fc_swap(tmp._ptr,_ptr);
if( _ptr == p._ptr ) return *this;
if( _ptr != nullptr ) _ptr->release();
_ptr = p._ptr;
if( _ptr != nullptr ) _ptr->retain();
return *this;
}
shared_ptr& operator=(shared_ptr&& p ) {

View file

@ -1,5 +1,4 @@
#ifndef _FC_SPIN_YIELD_LOCK_HPP_
#define _FC_SPIN_YIELD_LOCK_HPP_
#pragma once
namespace boost {
template<typename T> class atomic;
@ -38,4 +37,3 @@ namespace fc {
} // namespace fc
#endif // _FC_SPIN_YIELD_LOCK_HPP_

View file

@ -4,7 +4,10 @@
#include <iostream>
#include <string.h>
#include <fc/log.hpp>
#include <fc/mutex.hpp>
#include <fc/scoped_lock.hpp>
#include <string>
#include <boost/thread/mutex.hpp>
namespace fc {
ostream& operator<<( ostream& o, const char* v ) {
@ -32,18 +35,27 @@ namespace fc {
buf[write_pos&0xfffff] = c;
++write_pos;
auto tmp = read_ready; // copy read_ready because it is accessed from multiple threads
fc::promise<void>::ptr tmp;
{ // copy read_ready because it is accessed from multiple threads
fc::scoped_lock<boost::mutex> lock( read_ready_mutex );
tmp = read_ready;
}
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
fc::promise<void>::ptr tmp;
{ // copy read_ready because it is accessed from multiple threads
fc::scoped_lock<boost::mutex> lock( read_ready_mutex );
tmp = read_ready;
}
if( tmp && !tmp->ready() ) {
tmp->set_value();
}
}
boost::mutex read_ready_mutex;
fc::promise<void>::ptr read_ready;
fc::promise<void>::ptr write_ready;
@ -105,17 +117,34 @@ namespace fc {
return u;
}
cin_t::~cin_t() {
wlog( "~cin_t" );
/*
cin_buffer& b = get_cin_buffer();
if( b.read_ready ) {
b.read_ready->wait();
}
*/
}
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;
// b.read_ready = rr;
{ // copy read_ready because it is accessed from multiple threads
fc::scoped_lock<boost::mutex> lock( b.read_ready_mutex );
b.read_ready = rr;
}
if( b.write_pos - b.read_pos == 0 ) {
rr->wait();
}
b.read_ready.reset();
{ // copy read_ready because it is accessed from multiple threads
fc::scoped_lock<boost::mutex> lock( b.read_ready_mutex );
b.read_ready.reset();
}
}
if( b.eof ) return *this;
size_t r = readsome( buf, len );

View file

@ -5,9 +5,12 @@
namespace fc {
retainable::retainable()
:_ref_count(1) { }
:_ref_count(1) {
static_assert( sizeof(_ref_count) == sizeof(boost::atomic<int32_t>), "failed to reserve enough space" );
}
retainable::~retainable() {
assert( _ref_count <= 0 );
assert( _ref_count == 0 );
}
void retainable::retain() {
@ -15,8 +18,8 @@ namespace fc {
}
void retainable::release() {
if( 1 == ((boost::atomic<int32_t>*)&_ref_count)->fetch_sub(1, boost::memory_order_release ) ) {
boost::atomic_thread_fence(boost::memory_order_acquire);
if( 1 == ((boost::atomic<int32_t>*)&_ref_count)->fetch_sub(1, boost::memory_order_release ) ) {
delete this;
}
}