Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix #74 osx clang problems #732

Merged
merged 8 commits into from
May 24, 2017
108 changes: 69 additions & 39 deletions nestkernel/recording_device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ nest::RecordingDevice::Parameters_::Parameters_( const std::string& file_ext,
, user_set_precise_times_( false )
, user_set_precision_( false )
, binary_( false )
, fbuffer_size_( BUFSIZ ) // default buffer size as defined in <cstdio>
, fbuffer_size_( -1 ) // -1 marks use of default buffer
, label_()
, file_ext_( file_ext )
, filename_()
Expand Down Expand Up @@ -174,7 +174,7 @@ nest::RecordingDevice::Parameters_::get( const RecordingDevice& rd,

void
nest::RecordingDevice::Parameters_::set( const RecordingDevice& rd,
const Buffers_&,
const Buffers_& B,
const DictionaryDatum& d )
{
updateValue< std::string >( d, names::label, label_ );
Expand Down Expand Up @@ -204,18 +204,21 @@ nest::RecordingDevice::Parameters_::set( const RecordingDevice& rd,

updateValue< bool >( d, names::binary, binary_ );

long fbuffer_size;
long fbuffer_size = -1;
if ( updateValue< long >( d, names::fbuffer_size, fbuffer_size ) )
{
if ( fbuffer_size < 0 )
if ( B.fs_.is_open() )
{
throw BadProperty( "/fbuffer_size must be <= 0" );
throw BadProperty( "fbuffer_size cannot be set on open files." );
}
else

// prohibit negative sizes but allow Create_l_i_D to reset -1 on prototype
if ( fbuffer_size < 0
and not( rd.node_.get_vp() == -1 and fbuffer_size == -1 ) )
{
fbuffer_size_old_ = fbuffer_size_;
fbuffer_size_ = fbuffer_size;
throw BadProperty( "fbuffer_size must be >= 0." );
}
fbuffer_size_ = fbuffer_size;
}

updateValue< bool >( d, names::close_after_simulate, close_after_simulate_ );
Expand Down Expand Up @@ -445,8 +448,24 @@ nest::RecordingDevice::State_::set( const DictionaryDatum& d )
}
}

nest::RecordingDevice::Buffers_::Buffers_()
: fs_()
, fbuffer_( 0 )
, fbuffer_size_( -1 )
{
}

nest::RecordingDevice::Buffers_::~Buffers_()
{
if ( fbuffer_ )
{
delete[] fbuffer_;
}
}


/* ----------------------------------------------------------------
* Default and copy constructor for device
* Default and copy constructor and destructor for device
* ---------------------------------------------------------------- */

nest::RecordingDevice::RecordingDevice( const Node& n,
Expand All @@ -469,6 +488,7 @@ nest::RecordingDevice::RecordingDevice( const Node& n,
withport,
withrport )
, S_()
, B_()
{
}

Expand All @@ -479,10 +499,10 @@ nest::RecordingDevice::RecordingDevice( const Node& n,
, mode_( d.mode_ )
, P_( d.P_ )
, S_( d.S_ )
, B_() // do not copy
{
}


/* ----------------------------------------------------------------
* Device initialization functions
* ---------------------------------------------------------------- */
Expand All @@ -509,6 +529,8 @@ nest::RecordingDevice::init_buffers()
Device::init_buffers();

// we only close files here, opening is left to calibrate()
// we must not touch B_.fbuffer_ here, as it will be used
// as long as B_.fs_ exists.
if ( P_.close_on_reset_ && B_.fs_.is_open() )
{
B_.fs_.close();
Expand Down Expand Up @@ -550,6 +572,40 @@ nest::RecordingDevice::calibrate()
{
assert( not B_.fs_.is_open() );

// pubsetbuf() must be called before the opening file: otherwise, it has
// no effect (libstdc++) or may lead to undefined behavior (libc++), see
// http://en.cppreference.com/w/cpp/io/basic_filebuf/setbuf.
if ( P_.fbuffer_size_ >= 0 )
{
if ( B_.fbuffer_ )
{
delete[] B_.fbuffer_;
B_.fbuffer_ = 0;
}
// invariant: B_.fbuffer_ == 0

if ( P_.fbuffer_size_ > 0 )
{
B_.fbuffer_ = new char[ P_.fbuffer_size_ ];
}
// invariant: ( P_.fbuffer_size_ == 0 and B_.fbuffer_ == 0 )
// or
// ( P_.fbuffer_size_ > 0 and B_.fbuffer_ != 0 )

B_.fbuffer_size_ = P_.fbuffer_size_;

std::basic_streambuf< char >* res =
B_.fs_.rdbuf()->pubsetbuf( B_.fbuffer_, B_.fbuffer_size_ );

if ( res == 0 )
{
LOG( M_ERROR,
"RecordingDevice::calibrate()",
"Failed to set file buffer." );
throw IOError();
}
}

if ( kernel().io_manager.overwrite_files() )
{
if ( P_.binary_ )
Expand Down Expand Up @@ -590,23 +646,6 @@ nest::RecordingDevice::calibrate()
B_.fs_.open( P_.filename_.c_str() );
}
}

if ( P_.fbuffer_size_ != P_.fbuffer_size_old_ )
{
if ( P_.fbuffer_size_ == 0 )
{
B_.fs_.rdbuf()->pubsetbuf( 0, 0 );
}
else
{
std::vector< char >* buffer =
new std::vector< char >( P_.fbuffer_size_ );
B_.fs_.rdbuf()->pubsetbuf(
reinterpret_cast< char* >( &buffer[ 0 ] ), P_.fbuffer_size_ );
}

P_.fbuffer_size_old_ = P_.fbuffer_size_;
}
}

if ( not B_.fs_.good() )
Expand Down Expand Up @@ -641,17 +680,6 @@ nest::RecordingDevice::calibrate()
}

B_.fs_ << std::setprecision( P_.precision_ );

if ( P_.fbuffer_size_ != P_.fbuffer_size_old_ )
{
std::string msg = String::compose(
"Cannot set file buffer size, as the file is already "
"openeded with a buffer size of %1. Please close the "
"file first.",
P_.fbuffer_size_old_ );
LOG( M_ERROR, "RecordingDevice::calibrate()", msg );
throw IOError();
}
}
}

Expand All @@ -661,9 +689,11 @@ nest::RecordingDevice::post_run_cleanup()
if ( B_.fs_.is_open() )
{
if ( P_.flush_after_simulate_ )
{
B_.fs_.flush();
}

if ( !B_.fs_.good() )
if ( not B_.fs_.good() )
{
std::string msg =
String::compose( "I/O error while opening file '%1'", P_.filename_ );
Expand Down
27 changes: 19 additions & 8 deletions nestkernel/recording_device.h
Original file line number Diff line number Diff line change
Expand Up @@ -174,10 +174,12 @@ namespace nest
/binary - if set to true, data is written in binary mode to files
instead of ASCII. This setting affects file output only, not
screen output (default: false)
/fbuffer_size - the size of the buffer to use for writing to files. The
default size is determined by the implementation of the C++
standard library. To obtain an unbuffered file stream, use a
buffer size of 0.
/fbuffer_size - the size of the buffer to use for writing to files. Setting
this value to 0 will reduce buffering to a system-dependent
minimum. Set /flush_after_simulate to true to ensure that all
pending data is written to file before Simulate returns. A
value of -1 shows that the system default is in use. This
value can only be changed before Simulate is called.

Data recorded in memory is available through the following parameter:
/n_events - Number of events collected or sampled. n_events can be set to
Expand Down Expand Up @@ -472,6 +474,18 @@ class RecordingDevice : public Device
struct Buffers_
{
std::ofstream fs_; //!< the file to write the recorded data to

/**
* Manually managed output buffer.
*
* This pointer is zero unless the user explicitly sets fbuffer_size_
* to a value greater than zero.
*/
char* fbuffer_;
long fbuffer_size_; //!< size of fbuffer_; -1: not yet set

Buffers_();
~Buffers_();
};

// ------------------------------------------------------------------
Expand Down Expand Up @@ -499,9 +513,7 @@ class RecordingDevice : public Device
bool user_set_precision_; //!< true if user set precision

bool binary_; //!< true if to write files in binary mode instead of ASCII
long fbuffer_size_; //!< the buffer size to use when writing to file
long fbuffer_size_old_; //!< the buffer size to use when writing
//!< to file (old)
long fbuffer_size_; //!< output buffer size; -1 until set by user

std::string label_; //!< a user-defined label for symbolic device names.
std::string file_ext_; //!< the file name extension to use, without .
Expand Down Expand Up @@ -559,7 +571,6 @@ class RecordingDevice : public Device
Parameters_ P_;
State_ S_;
Buffers_ B_;
Buffers_ V_;
};

inline bool
Expand Down
8 changes: 6 additions & 2 deletions sli/processes.cc
Original file line number Diff line number Diff line change
Expand Up @@ -940,8 +940,12 @@ Processes::SetNonblockFunction::execute( SLIInterpreter* i ) const
void
Processes::CtermidFunction::execute( SLIInterpreter* i ) const
{
char term[] = "\0";
std::string termid = ctermid( term );
// ensure term buffer is sufficiently large and safely initialized
assert( L_ctermid > 0 );
char term[ L_ctermid ];
term[ 0 ] = '\0';

const std::string termid = ctermid( term );

i->OStack.push( Token( termid ) );
i->EStack.pop();
Expand Down
1 change: 1 addition & 0 deletions topology/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ set( topo_sources
grid_layer.h
mask.h
mask_impl.h
mask.cpp
grid_mask.h
ntree.h
ntree_impl.h
Expand Down
32 changes: 32 additions & 0 deletions topology/mask.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* mask.cpp
*
* This file is part of NEST.
*
* Copyright (C) 2004 The NEST Initiative
*
* NEST is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* NEST is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with NEST. If not, see <http://www.gnu.org/licenses/>.
*
*/

#include "mask.h"

// includes from sli
#include "lockptrdatum_impl.h"

// Explicit definition required to ensure visibility when compiling with
// clang under OSX. This must be outside namespace NEST, since the template
// is defined in the global namespace.
template class lockPTRDatum< nest::AbstractMask,
&nest::TopologyModule::MaskType >;
7 changes: 4 additions & 3 deletions topology/mask.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,10 @@

namespace nest
{
class TopologyModule;
class AbstractMask;

typedef lockPTRDatum< AbstractMask, &TopologyModule::MaskType > MaskDatum;


/**
* Abstract base class for masks with unspecified dimension.
Expand Down Expand Up @@ -92,8 +95,6 @@ class AbstractMask
virtual AbstractMask* minus_mask( const AbstractMask& other ) const = 0;
};

typedef lockPTRDatum< AbstractMask, &TopologyModule::MaskType > MaskDatum;

/**
* Abstract base class for masks with given dimension.
*/
Expand Down
4 changes: 0 additions & 4 deletions topology/topology_names.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@ const Name mean_x( "mean_x" );
const Name mean_y( "mean_y" );
const Name min( "min" );
const Name minor_axis( "minor_axis" );
const Name mu( "mu" );
const Name number_of_connections( "number_of_connections" );
const Name outer_radius( "outer_radius" );
const Name p_center( "p_center" );
Expand All @@ -85,11 +84,8 @@ const Name sigma_x( "sigma_x" );
const Name sigma_y( "sigma_y" );
const Name sources( "sources" );
const Name spherical( "spherical" );
const Name tau( "tau" );
const Name topology( "topology" );
const Name upper_right( "upper_right" );
const Name volume( "volume" );
// const Name x("x");
const Name y( "y" );
}
}
4 changes: 0 additions & 4 deletions topology/topology_names.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,6 @@ extern const Name mean_x;
extern const Name mean_y;
extern const Name min;
extern const Name minor_axis;
extern const Name mu;
extern const Name number_of_connections;
extern const Name outer_radius;
extern const Name p_center;
Expand All @@ -94,12 +93,9 @@ extern const Name sigma_x;
extern const Name sigma_y;
extern const Name sources;
extern const Name spherical;
extern const Name tau;
extern const Name topology;
extern const Name upper_right;
extern const Name volume;
// extern const Name x; // this name is already defined in nest_names
extern const Name y;
}
}

Expand Down
9 changes: 9 additions & 0 deletions topology/topology_parameter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,15 @@

#include "topology_parameter.h"

// includes from sli
#include "lockptrdatum_impl.h"

// Explicit definition required to ensure visibility when compiling with
// clang under OSX. This must be outside namespace NEST, since the template
// is defined in the global namespace.
template class lockPTRDatum< nest::TopologyParameter,
&nest::TopologyModule::ParameterType >;

namespace nest
{

Expand Down
Loading