<commit_before>#include "itkCommandLineArgumentParser.h"
#include "CommandLineArgumentHelper.h"

#include "itkImageSliceConstIteratorWithIndex.h"
#include "itkImageSliceIteratorWithIndex.h"

#include "itkImageFileReader.h"
#include "itkImageFileWriter.h"

//-------------------------------------------------------------------------------------

/** run: A macro to call a function. */
#define run(function,type,dim) \
if ( ComponentTypeIn == #type && Dimension == dim ) \
{ \
  typedef itk::Image< type, dim > InputImageType; \
  function< InputImageType >( inputFileName, outputFileName, everyOther, offset, direction ); \
  supported = true; \
}

//-------------------------------------------------------------------------------------

/** Declare ExtractEveryOtherSlice. */
template< class InputImageType >
void ExtractEveryOtherSlice(
  const std::string & inputFileName,
  const std::string & outputFileName,
  unsigned int everyOther,
  unsigned int offset,
  unsigned int direction );

/** Declare PrintHelp. */
void PrintHelp( void );

//-------------------------------------------------------------------------------------

int main( int argc, char **argv )
{
  /** Check arguments for help. */
  if ( argc < 3 || argc > 9 )
  {
    PrintHelp();
    return 1;
  }

  /** Create a command line argument parser. */
  itk::CommandLineArgumentParser::Pointer parser = itk::CommandLineArgumentParser::New();
  parser->SetCommandLineArguments( argc, argv );

  /** Get arguments. */
  std::string inputFileName = "";
  bool retin = parser->GetCommandLineArgument( "-in", inputFileName );

  std::string outputFileName = inputFileName.substr( 0, inputFileName.rfind( "." ) );
  outputFileName += "EveryOtherKExtracted.mhd";
  parser->GetCommandLineArgument( "-out", outputFileName );

  unsigned int everyOther = 2;
  parser->GetCommandLineArgument( "-K", everyOther );

  unsigned int offset = 0;
  parser->GetCommandLineArgument( "-of", offset );
  offset = offset % everyOther;

  unsigned int direction = 2;
  parser->GetCommandLineArgument( "-d", direction );

  /** Check if the required arguments are given. */
  if ( !retin )
  {
    std::cerr << "ERROR: You should specify \"-in\"." << std::endl;
    return 1;
  }

  /** Check everyOther. */
  if ( everyOther < 2 )
  {
    std::cout << "ERROR: K should be larger than 1." << std::endl;
    return 1;
  }

  /** Determine image properties. */
  std::string ComponentTypeIn = "short";
  std::string PixelType; //we don't use this
  unsigned int Dimension = 3;
  unsigned int NumberOfComponents = 1;
  std::vector<unsigned int> imagesize( Dimension, 0 );
  int retgip = GetImageProperties(
    inputFileName,
    PixelType,
    ComponentTypeIn,
    Dimension,
    NumberOfComponents,
    imagesize );
  if ( retgip != 0 )
  {
    return 1;
  }

  /** Check for vector images. */
  if ( NumberOfComponents > 1 )
  {
    std::cerr << "ERROR: The NumberOfComponents is larger than 1!" << std::endl;
    std::cerr << "Vector images are not supported." << std::endl;
    return 1;
  }

  /** Check for dimension. */
  if ( Dimension != 3 )
  {
    std::cerr << "ERROR: The image dimension equals " << Dimension << "." << std::endl;
    std::cerr << "Only 3D images are supported." << std::endl;
    return 1;
  }

  /** Get rid of the possible "_" in ComponentType. */
  ReplaceUnderscoreWithSpace( ComponentTypeIn );

  /** Check direction. */
  if ( direction + 1 > Dimension )
  {
    std::cout << "ERROR: direction should be 0, 1 or 2." << std::endl;
    return 1;
  }

  /** Run the program. */
  bool supported = false;
  try
  {
    run( ExtractEveryOtherSlice, unsigned char, 3 );
    run( ExtractEveryOtherSlice, char, 3 );
    run( ExtractEveryOtherSlice, unsigned short, 3 );
    run( ExtractEveryOtherSlice, short, 3 );
    run( ExtractEveryOtherSlice, float, 3 );
    run( ExtractEveryOtherSlice, double, 3 );
  }
  catch( itk::ExceptionObject &e )
  {
    std::cerr << "Caught ITK exception: " << e << std::endl;
    return 1;
  }
  if ( !supported )
  {
    std::cerr << "ERROR: this combination of pixeltype and dimension is not supported!" << std::endl;
    std::cerr
      << "pixel (component) type = " << PixelType
      << " ; dimension = " << Dimension
      << std::endl;
    return 1;
  }

  /** End program. */
  return 0;

} // end main

  /**
   * ******************* ExtractEveryOtherSlice *******************
   *
   * The ExtractEveryOtherSlice function templated over the input pixel type.
   */

template< class InputImageType >
void ExtractEveryOtherSlice(
  const std::string & inputFileName,
  const std::string & outputFileName,
  unsigned int everyOther,
  unsigned int offset,
  unsigned int direction )
{
  /** Typedefs. */
  typedef itk::ImageSliceConstIteratorWithIndex<
    InputImageType >                                  SliceConstIteratorType;
  typedef itk::ImageSliceIteratorWithIndex<
    InputImageType >                                  SliceIteratorType;
  typedef itk::ImageFileReader< InputImageType >      ReaderType;
  typedef itk::ImageFileWriter< InputImageType >      WriterType;
  typedef typename InputImageType::RegionType         RegionType;
  typedef typename RegionType::IndexType              IndexType;
  typedef typename InputImageType::SizeType           SizeType;

  /** Read in the inputImage. */
  typename ReaderType::Pointer reader = ReaderType::New();
  reader->SetFileName( inputFileName.c_str() );
  reader->Update();

  /** Define size of output image. */
  SizeType sizeIn = reader->GetOutput()->GetLargestPossibleRegion().GetSize();
  SizeType sizeOut = sizeIn;
  float newSize = vcl_ceil(
    ( static_cast<float>( sizeOut[ direction ] - offset ) )
    / static_cast<float>( everyOther ) );
  sizeOut[ direction ] = static_cast<unsigned int>( newSize );

  /** Define region of output image. */
  RegionType region;
  region.SetIndex( reader->GetOutput()->GetLargestPossibleRegion().GetIndex() );
  region.SetSize( sizeOut );

  /** Create output image. */
  typename InputImageType::Pointer outputImage = InputImageType::New();
  outputImage->SetSpacing( reader->GetOutput()->GetSpacing() );
  outputImage->SetOrigin( reader->GetOutput()->GetOrigin() );
  outputImage->SetRegions( region );
  outputImage->Allocate();

  /** Create iterators. */
  SliceConstIteratorType itIn( reader->GetOutput(), reader->GetOutput()->GetLargestPossibleRegion() );
  SliceIteratorType itOut( outputImage, outputImage->GetLargestPossibleRegion() );

  /** Set direction, default slice = z. */
  if ( direction == 0 )
  {
    itIn.SetFirstDirection(1);
    itIn.SetSecondDirection(2);
    itOut.SetFirstDirection(1);
    itOut.SetSecondDirection(2);
  }
  else if ( direction == 1 )
  {
    itIn.SetFirstDirection(0);
    itIn.SetSecondDirection(2);
    itOut.SetFirstDirection(0);
    itOut.SetSecondDirection(2);
  }
  else if ( direction == 2 )
  {
    itIn.SetFirstDirection(0);
    itIn.SetSecondDirection(1);
    itOut.SetFirstDirection(0);
    itOut.SetSecondDirection(1);
  }

  /** Initialize iterators. */
  itIn.GoToBegin();
  itOut.GoToBegin();
  IndexType index= itIn.GetIndex();
  index[ direction ] += offset;
  itIn.SetIndex( index );

  /** Loop over images. */
  while( !itOut.IsAtEnd() )
  {
    while( !itOut.IsAtEndOfSlice() )
    {
      while( !itOut.IsAtEndOfLine() )
      {
        itOut.Set( itIn.Get() );
        ++itIn;
        ++itOut;
      }
      itIn.NextLine();
      itOut.NextLine();
    }
    itIn.NextSlice();
    itOut.NextSlice();

    /** Skip some slices in inputImage. */
    index = itIn.GetIndex();
    for ( unsigned int i = 1; i < everyOther; i++ )
    {
      index[ direction ]++;
    }
    itIn.SetIndex( index );
  }

  /** Write the output image. */
  typename WriterType::Pointer writer = WriterType::New();
  writer->SetFileName( outputFileName.c_str() );
  writer->SetInput( outputImage );
  writer->Update();

} // end ExtractEveryOtherSlice()

  /**
   * ******************* PrintHelp *******************
   */

void PrintHelp( void )
{
  std::cout << "Usage:" << std::endl << "pxextracteveryotherslice" << std::endl;
  std::cout << "  -in      inputFilename" << std::endl;
  std::cout << "  [-out]   outputFilename, default in + EveryOtherKExtracted.mhd" << std::endl;
  std::cout << "  [-K]     every other slice K, default 2" << std::endl;
  std::cout << "  [-of]    offset, default 0" << std::endl;
  std::cout << "  [-d]     direction, default is z-axes" << std::endl;
  std::cout << "Supported: 3D, (unsigned) char, (unsigned) short, float, double." << std::endl;

} // end PrintHelp()

<commit_msg>New style arguments for extracteveryotherslice<commit_after>#include "itkCommandLineArgumentParser.h"
#include "CommandLineArgumentHelper.h"

#include "itkImageSliceConstIteratorWithIndex.h"
#include "itkImageSliceIteratorWithIndex.h"

#include "itkImageFileReader.h"
#include "itkImageFileWriter.h"

//-------------------------------------------------------------------------------------

/** run: A macro to call a function. */
#define run(function,type,dim) \
if ( ComponentTypeIn == #type && Dimension == dim ) \
{ \
  typedef itk::Image< type, dim > InputImageType; \
  function< InputImageType >( inputFileName, outputFileName, everyOther, offset, direction ); \
  supported = true; \
}

//-------------------------------------------------------------------------------------

/** Declare ExtractEveryOtherSlice. */
template< class InputImageType >
void ExtractEveryOtherSlice(
  const std::string & inputFileName,
  const std::string & outputFileName,
  unsigned int everyOther,
  unsigned int offset,
  unsigned int direction );

/** Declare PrintHelp. */
std::string PrintHelp( void );

//-------------------------------------------------------------------------------------

int main( int argc, char **argv )
{
  /** Create a command line argument parser. */
  itk::CommandLineArgumentParser::Pointer parser = itk::CommandLineArgumentParser::New();
  parser->SetCommandLineArguments( argc, argv );
  parser->SetProgramHelpText(PrintHelp());

  parser->MarkArgumentAsRequired( "-in", "The input filename." );

  bool validateArguments = parser->CheckForRequiredArguments();

  if(!validateArguments)
  {
    return EXIT_FAILURE;
  }

  /** Get arguments. */
  std::string inputFileName = "";
  parser->GetCommandLineArgument( "-in", inputFileName );

  std::string outputFileName = inputFileName.substr( 0, inputFileName.rfind( "." ) );
  outputFileName += "EveryOtherKExtracted.mhd";
  parser->GetCommandLineArgument( "-out", outputFileName );

  unsigned int everyOther = 2;
  parser->GetCommandLineArgument( "-K", everyOther );

  unsigned int offset = 0;
  parser->GetCommandLineArgument( "-of", offset );
  offset = offset % everyOther;

  unsigned int direction = 2;
  parser->GetCommandLineArgument( "-d", direction );

  /** Check everyOther. */
  if ( everyOther < 2 )
  {
    std::cout << "ERROR: K should be larger than 1." << std::endl;
    return 1;
  }

  /** Determine image properties. */
  std::string ComponentTypeIn = "short";
  std::string PixelType; //we don't use this
  unsigned int Dimension = 3;
  unsigned int NumberOfComponents = 1;
  std::vector<unsigned int> imagesize( Dimension, 0 );
  int retgip = GetImageProperties(
    inputFileName,
    PixelType,
    ComponentTypeIn,
    Dimension,
    NumberOfComponents,
    imagesize );
  if ( retgip != 0 )
  {
    return 1;
  }

  /** Check for vector images. */
  if ( NumberOfComponents > 1 )
  {
    std::cerr << "ERROR: The NumberOfComponents is larger than 1!" << std::endl;
    std::cerr << "Vector images are not supported." << std::endl;
    return 1;
  }

  /** Check for dimension. */
  if ( Dimension != 3 )
  {
    std::cerr << "ERROR: The image dimension equals " << Dimension << "." << std::endl;
    std::cerr << "Only 3D images are supported." << std::endl;
    return 1;
  }

  /** Get rid of the possible "_" in ComponentType. */
  ReplaceUnderscoreWithSpace( ComponentTypeIn );

  /** Check direction. */
  if ( direction + 1 > Dimension )
  {
    std::cout << "ERROR: direction should be 0, 1 or 2." << std::endl;
    return 1;
  }

  /** Run the program. */
  bool supported = false;
  try
  {
    run( ExtractEveryOtherSlice, unsigned char, 3 );
    run( ExtractEveryOtherSlice, char, 3 );
    run( ExtractEveryOtherSlice, unsigned short, 3 );
    run( ExtractEveryOtherSlice, short, 3 );
    run( ExtractEveryOtherSlice, float, 3 );
    run( ExtractEveryOtherSlice, double, 3 );
  }
  catch( itk::ExceptionObject &e )
  {
    std::cerr << "Caught ITK exception: " << e << std::endl;
    return 1;
  }
  if ( !supported )
  {
    std::cerr << "ERROR: this combination of pixeltype and dimension is not supported!" << std::endl;
    std::cerr
      << "pixel (component) type = " << PixelType
      << " ; dimension = " << Dimension
      << std::endl;
    return 1;
  }

  /** End program. */
  return 0;

} // end main

  /**
   * ******************* ExtractEveryOtherSlice *******************
   *
   * The ExtractEveryOtherSlice function templated over the input pixel type.
   */

template< class InputImageType >
void ExtractEveryOtherSlice(
  const std::string & inputFileName,
  const std::string & outputFileName,
  unsigned int everyOther,
  unsigned int offset,
  unsigned int direction )
{
  /** Typedefs. */
  typedef itk::ImageSliceConstIteratorWithIndex<
    InputImageType >                                  SliceConstIteratorType;
  typedef itk::ImageSliceIteratorWithIndex<
    InputImageType >                                  SliceIteratorType;
  typedef itk::ImageFileReader< InputImageType >      ReaderType;
  typedef itk::ImageFileWriter< InputImageType >      WriterType;
  typedef typename InputImageType::RegionType         RegionType;
  typedef typename RegionType::IndexType              IndexType;
  typedef typename InputImageType::SizeType           SizeType;

  /** Read in the inputImage. */
  typename ReaderType::Pointer reader = ReaderType::New();
  reader->SetFileName( inputFileName.c_str() );
  reader->Update();

  /** Define size of output image. */
  SizeType sizeIn = reader->GetOutput()->GetLargestPossibleRegion().GetSize();
  SizeType sizeOut = sizeIn;
  float newSize = vcl_ceil(
    ( static_cast<float>( sizeOut[ direction ] - offset ) )
    / static_cast<float>( everyOther ) );
  sizeOut[ direction ] = static_cast<unsigned int>( newSize );

  /** Define region of output image. */
  RegionType region;
  region.SetIndex( reader->GetOutput()->GetLargestPossibleRegion().GetIndex() );
  region.SetSize( sizeOut );

  /** Create output image. */
  typename InputImageType::Pointer outputImage = InputImageType::New();
  outputImage->SetSpacing( reader->GetOutput()->GetSpacing() );
  outputImage->SetOrigin( reader->GetOutput()->GetOrigin() );
  outputImage->SetRegions( region );
  outputImage->Allocate();

  /** Create iterators. */
  SliceConstIteratorType itIn( reader->GetOutput(), reader->GetOutput()->GetLargestPossibleRegion() );
  SliceIteratorType itOut( outputImage, outputImage->GetLargestPossibleRegion() );

  /** Set direction, default slice = z. */
  if ( direction == 0 )
  {
    itIn.SetFirstDirection(1);
    itIn.SetSecondDirection(2);
    itOut.SetFirstDirection(1);
    itOut.SetSecondDirection(2);
  }
  else if ( direction == 1 )
  {
    itIn.SetFirstDirection(0);
    itIn.SetSecondDirection(2);
    itOut.SetFirstDirection(0);
    itOut.SetSecondDirection(2);
  }
  else if ( direction == 2 )
  {
    itIn.SetFirstDirection(0);
    itIn.SetSecondDirection(1);
    itOut.SetFirstDirection(0);
    itOut.SetSecondDirection(1);
  }

  /** Initialize iterators. */
  itIn.GoToBegin();
  itOut.GoToBegin();
  IndexType index= itIn.GetIndex();
  index[ direction ] += offset;
  itIn.SetIndex( index );

  /** Loop over images. */
  while( !itOut.IsAtEnd() )
  {
    while( !itOut.IsAtEndOfSlice() )
    {
      while( !itOut.IsAtEndOfLine() )
      {
        itOut.Set( itIn.Get() );
        ++itIn;
        ++itOut;
      }
      itIn.NextLine();
      itOut.NextLine();
    }
    itIn.NextSlice();
    itOut.NextSlice();

    /** Skip some slices in inputImage. */
    index = itIn.GetIndex();
    for ( unsigned int i = 1; i < everyOther; i++ )
    {
      index[ direction ]++;
    }
    itIn.SetIndex( index );
  }

  /** Write the output image. */
  typename WriterType::Pointer writer = WriterType::New();
  writer->SetFileName( outputFileName.c_str() );
  writer->SetInput( outputImage );
  writer->Update();

} // end ExtractEveryOtherSlice()

  /**
   * ******************* PrintHelp *******************
   */

std::string PrintHelp( void )
{
  std::string helpText = "Usage: \
  pxextracteveryotherslice \
    -in      inputFilename \
    [-out]   outputFilename, default in + EveryOtherKExtracted.mhd \
    [-K]     every other slice K, default 2 \
    [-of]    offset, default 0 \
    [-d]     direction, default is z-axes \
  Supported: 3D, (unsigned) char, (unsigned) short, float, double.";
  return helpText;

} // end PrintHelp()

<|endoftext|>


<commit_before>#include "xcint.hpp"

static struct alias_data aliases_array[XC_MAX_ALIASES] =
{
  {"null","No functional",{{"slaterx",0.0}} },
  {"lda","Slater exchange and VWN5 correlation",{{"slaterx",1.0},{"vwn5c",1.0}} },
  {"blyp","Becke exchange and LYP correlation",{{"beckex",1.0},{"lypc",1.0}} },
  {"pbe","PBE exchange and correlation",{{"pbex",1.0},{"pbec",1.0}} },
  {"bp86","Becke-Perdew 1986",{{"beckex",1.0},{"p86c",1.0}} },
  {"kt1","Keal-Tozer 2",{{"slaterx",1.},{"ktx",-0.006},{"vwn5c",1.}} },
  {"kt2","Keal-Tozer 2",{{"slaterx",1.07173},{"ktx",-0.006},{"vwn5c",0.576727}} },
  {"kt3","Keal-Tozer 3",{{"slaterx",1.092},{"ktx",-0.004},{"optxcorr",-0.925452},{"lypc",0.864409}} },
  {"ldaerf","Short-range exchange and correlation LDA functional",{{"ldaerfx",1.0},{"ldaerfc",1.0}}},
  // Hybrid Functionals
  {"pbe0","Perdew-Burke-Ernzerhof",{{"pbex",0.75},{"pbec",1.0},{"exx",0.25}} },
  {"b3lyp","Becke-3-paramater-LYP (VWN5 form)", {{"slaterx",0.80},{"beckecorrx",0.72},{"lypc",0.81},{"vwn5c",0.19},{"exx",0.20}} },
  {"m06","M06", {{"m06c",1.0},{"m06x",1.0}} },
  {"m06-2x","M06 2X", {{"m06x2c",1.0},{"m06x2x",1.0}} },
  {"m06L","M06 L", {{"m06lc",1.0},{"m06lx",1.0}} },
  {"b3lyp-g","Becke-3-paramater-LYP (VWN3 form)", {{"slaterx",0.80},{"beckecorrx",0.72},{"lypc",0.81},{"vwn3c",0.19},{"exx",0.20}} },
  {"b3p86","Becke-3-paramater-LYP (VWN5 form)", {{"slaterx",0.80},{"beckecorrx",0.72},{"p86corrc",0.81},{"vwn5c",1.0},{"exx",0.20}} },
  {"b3p86-g","Becke-3-paramater-LYP (VWN3 form)", {{"slaterx",0.80},{"beckecorrx",0.72},{"p86corrc",0.81},{"vwn3c",1.0},{"exx",0.20}} },
  {"bpw91","Becke 88 exchange+PW91",{{"beckex",1.0},{"pw91c",1.0}} },
  {"b97","B97 exchange and correlation", {{"b97x",1.0},{"b97c",1.0},{"exx",0.1943}} },
  {"b97-1","B97-1 exchange and correlation", {{"b97_1x",1.0},{"b97_1c",1.0},{"exx",0.21}} },
  {"b97_2","B97-2 exchange and correlation", {{"b97_2x",1.0},{"b97_2c",1.0},{"exx",0.21}} },
  // Some of these are there to match the names used in Dalton
  {"vwn","VWN5 correlation",{{"vwn5c",1.0}}},
  {"vwn3","VWN5 correlation",{{"vwn3c",1.0}}},
  {"svwn","Slater exchange and VWN5 correlation",{{"slaterx",1.0},{"vwn5c",1.0}} },
  {"svwn5","Slater exchange and VWN5 correlation",{{"slaterx",1.0},{"vwn5c",1.0}} },
  {"svwn3","Slater exchange and VWN3 correlation",{{"slaterx",1.0},{"vwn3c",1.0}} },
  {"becke","Becke exchange",{{"beckecorrx",1.0}}},
  {"slater","Slater exchange",{{"slaterx",1.0}}},
  {"olyp","LYP correlation and OPTX exchange",{{"lypc",1.0},{"optx",1.0}}},
  // ADMM exchange funtional corrections
  {"B88X","Becke exchange",{{"slaterx",1.},{"beckecorrx",1.0}} },
  {"LDAX","Slater exchange",{{"slaterx",1.}} },
  {"PBEX","PBE exchange",{{"pbex",1.0}} },
  {"KT3X","Keal-Tozer 3 exchange",{{"slaterx",1.092},{"ktx",-0.004},{"optxcorr",-0.925452}} },
  {"OPTX","OptX exchange",{{"slaterx",1.05151},{"optxcorr",-1.43169}} },
};

// TODO: OLYP

struct alias_data *xcint_aliases = aliases_array;
<commit_msg>More aliases for Dalton<commit_after>#include "xcint.hpp"

static struct alias_data aliases_array[XC_MAX_ALIASES] =
{
  {"null","No functional",{{"slaterx",0.0}} },
  {"lda","Slater exchange and VWN5 correlation",{{"slaterx",1.0},{"vwn5c",1.0}} },
  {"blyp","Becke exchange and LYP correlation",{{"beckex",1.0},{"lypc",1.0}} },
  {"pbe","PBE exchange and correlation",{{"pbex",1.0},{"pbec",1.0}} },
  {"bp86","Becke-Perdew 1986",{{"beckex",1.0},{"p86c",1.0}} },
  {"kt1","Keal-Tozer 2",{{"slaterx",1.},{"ktx",-0.006},{"vwn5c",1.}} },
  {"kt2","Keal-Tozer 2",{{"slaterx",1.07173},{"ktx",-0.006},{"vwn5c",0.576727}} },
  {"kt3","Keal-Tozer 3",{{"slaterx",1.092},{"ktx",-0.004},{"optxcorr",-0.925452},{"lypc",0.864409}} },
  {"ldaerf","Short-range exchange and correlation LDA functional",{{"ldaerfx",1.0},{"ldaerfc",1.0}}},
  // Hybrid Functionals
  {"pbe0","Perdew-Burke-Ernzerhof",{{"pbex",0.75},{"pbec",1.0},{"exx",0.25}} },
  {"b3lyp","Becke-3-paramater-LYP (VWN5 form)", {{"slaterx",0.80},{"beckecorrx",0.72},{"lypc",0.81},{"vwn5c",0.19},{"exx",0.20}} },
  {"m06","M06", {{"m06c",1.0},{"m06x",1.0}} },
  {"m06-2x","M06 2X", {{"m06x2c",1.0},{"m06x2x",1.0}} },
  {"m06L","M06 L", {{"m06lc",1.0},{"m06lx",1.0}} },
  {"b3lyp-g","Becke-3-paramater-LYP (VWN3 form)", {{"slaterx",0.80},{"beckecorrx",0.72},{"lypc",0.81},{"vwn3c",0.19},{"exx",0.20}} },
  {"b3p86","Becke-3-paramater-LYP (VWN5 form)", {{"slaterx",0.80},{"beckecorrx",0.72},{"p86corrc",0.81},{"vwn5c",1.0},{"exx",0.20}} },
  {"b3p86-g","Becke-3-paramater-LYP (VWN3 form)", {{"slaterx",0.80},{"beckecorrx",0.72},{"p86corrc",0.81},{"vwn3c",1.0},{"exx",0.20}} },
  {"bpw91","Becke 88 exchange+PW91",{{"beckex",1.0},{"pw91c",1.0}} },
  {"b97","B97 exchange and correlation", {{"b97x",1.0},{"b97c",1.0},{"exx",0.1943}} },
  {"b97-1","B97-1 exchange and correlation", {{"b97_1x",1.0},{"b97_1c",1.0},{"exx",0.21}} },
  {"b97_2","B97-2 exchange and correlation", {{"b97_2x",1.0},{"b97_2c",1.0},{"exx",0.21}} },
  // Some of these are there to match the names used in Dalton
  {"vwn","VWN5 correlation",{{"vwn5c",1.0}}},
  {"vwn5","VWN5 correlation",{{"vwn5c",1.0}}},
  {"vwn3","VWN5 correlation",{{"vwn3c",1.0}}},
  {"svwn","Slater exchange and VWN5 correlation",{{"slaterx",1.0},{"vwn5c",1.0}} },
  {"svwn5","Slater exchange and VWN5 correlation",{{"slaterx",1.0},{"vwn5c",1.0}} },
  {"svwn3","Slater exchange and VWN3 correlation",{{"slaterx",1.0},{"vwn3c",1.0}} },
  {"becke","Becke exchange",{{"beckecorrx",1.0}}},
  {"slater","Slater exchange",{{"slaterx",1.0}}},
  {"olyp","LYP correlation and OPTX exchange",{{"lypc",1.0},{"optx",1.0}}},
  {"lyp","LYP correlation",{{"lypc",1.0}}},
  // ADMM exchange funtional corrections
  {"B88X","Becke exchange",{{"slaterx",1.},{"beckecorrx",1.0}} },
  {"LDAX","Slater exchange",{{"slaterx",1.}} },
  {"PBEX","PBE exchange",{{"pbex",1.0}} },
  {"KT3X","Keal-Tozer 3 exchange",{{"slaterx",1.092},{"ktx",-0.004},{"optxcorr",-0.925452}} },
  {"OPTX","OptX exchange",{{"slaterx",1.05151},{"optxcorr",-1.43169}} },
  {"cam_compx","Complementary part of CAM exchange",{{"beckex",1.0},{"beckecamx",-1.0}} },
};

// TODO: OLYP

struct alias_data *xcint_aliases = aliases_array;
<|endoftext|>


<commit_before>#include "vtkConditionVariable.h"
#include "vtkMultiThreader.h"

#include <stdlib.h>

// For vtkSleep
#include "vtkWindows.h"
#include <ctype.h>
#include <time.h>

// Cross platform sleep (horked from vtkGeoTerrain.cxx)
inline void vtkSleep( double duration )
{
  duration = duration; // avoid warnings
  // sleep according to OS preference
#ifdef _WIN32
  Sleep( (int)( 1000 * duration ) );
#elif defined(__FreeBSD__) || defined(__linux__) || defined(sgi)
  struct timespec sleep_time, dummy;
  sleep_time.tv_sec = static_cast<int>( duration );
  sleep_time.tv_nsec = static_cast<int>( 1000000000 * ( duration - sleep_time.tv_sec ) );
  nanosleep( &sleep_time, &dummy );
#endif
}

typedef struct {
  vtkMutexLock* Lock;
  vtkConditionVariable* Condition;
  int Done;
  int NumberOfWorkers;
} vtkThreadUserData;

VTK_THREAD_RETURN_TYPE vtkTestCondVarThread( void* arg )
{
  int threadId = static_cast<vtkMultiThreader::ThreadInfo*>(arg)->ThreadID;
  int threadCount = static_cast<vtkMultiThreader::ThreadInfo*>(arg)->NumberOfThreads;
  vtkThreadUserData* td = static_cast<vtkThreadUserData*>(
    static_cast<vtkMultiThreader::ThreadInfo*>(arg)->UserData );
  if ( td )
    {
    if ( threadId == 0 )
      {
      td->Done = 0;
      td->Lock->Lock();
      cout << "Thread " << ( threadId + 1 ) << " of " << threadCount << " initializing.\n";
      cout.flush();
      td->Lock->Unlock();

      int i;
      for ( i = 0; i < 2 * threadCount; ++ i )
        {
        td->Lock->Lock();
        cout << "Signaling (count " << i << ")...\n";
        cout.flush();
        td->Lock->Unlock();
        td->Condition->Signal();

        //sleep( 1 );
        }

      i = 0;
      do
        {
        td->Lock->Lock();
        td->Done = 1;
        cout << "Broadcasting...\n";
        cout.flush();
        td->Lock->Unlock();
        td->Condition->Broadcast();
        vtkSleep( 0.2 ); // 0.2 s between broadcasts
        }
      while ( td->NumberOfWorkers > 0 && ( i ++ < 1000 ) );
      if ( i >= 1000 )
        {
        exit( 2 );
        }
      }
    else
      {
      // Wait for thread 0 to initialize... Ugly but effective
      while ( td->Done < 0 )
        {
        vtkSleep( 0.2 ); // 0.2 s between checking
        }

      // Wait for the condition and then note we were signaled.
      while ( td->Done <= 0 )
        {
        td->Lock->Lock();
        cout << " Thread " << ( threadId + 1 ) << " waiting.\n";
        cout.flush();
        td->Condition->Wait( td->Lock );
        cout << " Thread " << ( threadId + 1 ) << " responded.\n";
        cout.flush();
        td->Lock->Unlock();
        }
      -- td->NumberOfWorkers;
      }

    td->Lock->Lock();
    cout << "  Thread " << ( threadId + 1 ) << " of " << threadCount << " exiting.\n";
    cout.flush();
    td->Lock->Unlock();
    }
  else
    {
    cout << "No thread data!\n";
    cout << "  Thread " << ( threadId + 1 ) << " of " << threadCount << " exiting.\n";
    -- td->NumberOfWorkers;
    cout.flush();
    }

  return VTK_THREAD_RETURN_VALUE;
}

int TestConditionVariable( int, char*[] )
{
  vtkMultiThreader* threader = vtkMultiThreader::New();
  int numThreads = threader->GetNumberOfThreads();

  vtkThreadUserData data;
  data.Lock = vtkMutexLock::New();
  data.Condition = vtkConditionVariable::New();
  data.Done = -1;
  data.NumberOfWorkers = numThreads - 1;

  threader->SetNumberOfThreads( numThreads );
  threader->SetSingleMethod( vtkTestCondVarThread, &data );
  threader->SingleMethodExecute();

  cout << "Done with threader.\n";
  cout.flush();

  vtkIndent indent;
  indent = indent.GetNextIndent();
  data.Condition->PrintSelf( cout, indent );

  data.Lock->Delete();
  data.Condition->Delete();
  threader->Delete();
  return 0;
}
<commit_msg>BUG: See if this eliminates what appears to be a race condition in      the vtkConditionVariable test.<commit_after>#include "vtkConditionVariable.h"
#include "vtkMultiThreader.h"

#include <stdlib.h>

// For vtkSleep
#include "vtkWindows.h"
#include <ctype.h>
#include <time.h>

// Cross platform sleep (horked from vtkGeoTerrain.cxx)
inline void vtkSleep( double duration )
{
  duration = duration; // avoid warnings
  // sleep according to OS preference
#ifdef _WIN32
  Sleep( (int)( 1000 * duration ) );
#elif defined(__FreeBSD__) || defined(__linux__) || defined(sgi)
  struct timespec sleep_time, dummy;
  sleep_time.tv_sec = static_cast<int>( duration );
  sleep_time.tv_nsec = static_cast<int>( 1000000000 * ( duration - sleep_time.tv_sec ) );
  nanosleep( &sleep_time, &dummy );
#endif
}

typedef struct {
  vtkMutexLock* Lock;
  vtkConditionVariable* Condition;
  int Done;
  int NumberOfWorkers;
} vtkThreadUserData;

VTK_THREAD_RETURN_TYPE vtkTestCondVarThread( void* arg )
{
  int threadId = static_cast<vtkMultiThreader::ThreadInfo*>(arg)->ThreadID;
  int threadCount = static_cast<vtkMultiThreader::ThreadInfo*>(arg)->NumberOfThreads;
  vtkThreadUserData* td = static_cast<vtkThreadUserData*>(
    static_cast<vtkMultiThreader::ThreadInfo*>(arg)->UserData );
  if ( td )
    {
    if ( threadId == 0 )
      {
      td->Done = 0;
      td->Lock->Lock();
      cout << "Thread " << ( threadId + 1 ) << " of " << threadCount << " initializing.\n";
      cout.flush();
      td->Lock->Unlock();

      int i;
      for ( i = 0; i < 2 * threadCount; ++ i )
        {
        td->Lock->Lock();
        cout << "Signaling (count " << i << ")...\n";
        cout.flush();
        td->Lock->Unlock();
        td->Condition->Signal();

        //sleep( 1 );
        }

      i = 0;
      do
        {
        td->Lock->Lock();
        td->Done = 1;
        cout << "Broadcasting...\n";
        cout.flush();
        td->Lock->Unlock();
        td->Condition->Broadcast();
        vtkSleep( 0.2 ); // 0.2 s between broadcasts
        }
      while ( td->NumberOfWorkers > 0 && ( i ++ < 1000 ) );
      if ( i >= 1000 )
        {
        exit( 2 );
        }
      }
    else
      {
      // Wait for thread 0 to initialize... Ugly but effective
      while ( td->Done < 0 )
        {
        vtkSleep( 0.2 ); // 0.2 s between checking
        }

      // Wait for the condition and then note we were signaled.
      while ( td->Done <= 0 )
        {
        td->Lock->Lock();
        cout << " Thread " << ( threadId + 1 ) << " waiting.\n";
        cout.flush();
        td->Condition->Wait( td->Lock );
        cout << " Thread " << ( threadId + 1 ) << " responded.\n";
        cout.flush();
        td->Lock->Unlock();
        }
      td->Lock->Lock();
      -- td->NumberOfWorkers;
      td->Lock->Unlock();
      }

    td->Lock->Lock();
    cout << "  Thread " << ( threadId + 1 ) << " of " << threadCount << " exiting.\n";
    cout.flush();
    td->Lock->Unlock();
    }
  else
    {
    cout << "No thread data!\n";
    cout << "  Thread " << ( threadId + 1 ) << " of " << threadCount << " exiting.\n";
    -- td->NumberOfWorkers;
    cout.flush();
    }

  return VTK_THREAD_RETURN_VALUE;
}

int TestConditionVariable( int, char*[] )
{
  vtkMultiThreader* threader = vtkMultiThreader::New();
  int numThreads = threader->GetNumberOfThreads();

  vtkThreadUserData data;
  data.Lock = vtkMutexLock::New();
  data.Condition = vtkConditionVariable::New();
  data.Done = -1;
  data.NumberOfWorkers = numThreads - 1;

  threader->SetNumberOfThreads( numThreads );
  threader->SetSingleMethod( vtkTestCondVarThread, &data );
  threader->SingleMethodExecute();

  cout << "Done with threader.\n";
  cout.flush();

  vtkIndent indent;
  indent = indent.GetNextIndent();
  data.Condition->PrintSelf( cout, indent );

  data.Lock->Delete();
  data.Condition->Delete();
  threader->Delete();
  return 0;
}
<|endoftext|>


<commit_before>
#ifndef __BUFFER_CACHE_WRITEBACK_IMPL_HPP__
#define __BUFFER_CACHE_WRITEBACK_IMPL_HPP__

template <class config_t>
writeback_tmpl_t<config_t>::writeback_tmpl_t(
        cache_t *cache,
        bool wait_for_flush,
        unsigned int safety_timer_ms,
        unsigned int force_flush_threshold)
    : safety_timer(NULL),
      wait_for_flush(wait_for_flush),
      safety_timer_ms(safety_timer_ms),
      force_flush_threshold(force_flush_threshold),
      cache(cache),
      num_txns(0),
      shutdown_callback(NULL),
      final_sync(NULL),
      state(state_none),
      transaction(NULL) {
}

template <class config_t>
writeback_tmpl_t<config_t>::~writeback_tmpl_t() {
    gdelete(flush_lock);
}

template <class config_t>
void writeback_tmpl_t<config_t>::start() {
    flush_lock =
        gnew<rwi_lock_t>(&get_cpu_context()->event_queue->message_hub,
                         get_cpu_context()->event_queue->queue_id);
}

template <class config_t>
void writeback_tmpl_t<config_t>::shutdown(sync_callback_t *callback) {
    assert(shutdown_callback == NULL);
    shutdown_callback = callback;
    if (!num_txns && state == state_none) // If num_txns, commit() will do this
        sync(callback);
}

template <class config_t>
void writeback_tmpl_t<config_t>::sync(sync_callback_t *callback) {
    sync_callbacks.push_back(callback);
    // Start a new writeback process if one isn't in progress.
    if (state == state_none)
        writeback(NULL);
}

template <class config_t>
bool writeback_tmpl_t<config_t>::begin_transaction(transaction_t *txn) {
    assert(txn->get_access() == rwi_read || txn->get_access() == rwi_write);
    // TODO(NNW): If there's ever any asynchrony between socket reads and
    // begin_transaction, we'll need a better check here.
    assert(shutdown_callback == NULL || final_sync);
    num_txns++;
    if (txn->get_access() == rwi_read)
        return true;
    bool locked = flush_lock->lock(rwi_read, txn);
    return locked;
}

template <class config_t>
bool writeback_tmpl_t<config_t>::commit(transaction_t *txn,
        transaction_commit_callback_t *callback) {
    if (!--num_txns && shutdown_callback != NULL) {
        // All txns shut down, start final sync.
        sync(shutdown_callback);
    }
    if (txn->get_access() == rwi_read)
        return true;
    flush_lock->unlock();

    if (state == state_none) {
        /* At the end of every write transaction, check if the number of dirty blocks exceeds the
        threshold to force writeback to start. */
        if (num_dirty_blocks() > force_flush_threshold) {
            writeback(NULL);
        }
        /* Otherwise, start the safety timer so that the modified data doesn't sit in memory for too
        long without being written to disk. */
        else if (!safety_timer && safety_timer_ms != NEVER_FLUSH) {
            safety_timer = get_cpu_context()->event_queue->
                fire_timer_once(safety_timer_ms, safety_timer_callback, this);
        }
    }

    if (!wait_for_flush)
        return true;

    txns.push_back(new txn_state_t(txn, callback));
    return false;
}

template <class config_t>
void writeback_tmpl_t<config_t>::aio_complete(buf_t *buf, bool written) {
    if (written)
        writeback(buf);
}

template <class config_t>
unsigned int writeback_tmpl_t<config_t>::num_dirty_blocks() {
    return dirty_bufs.size();
}

#ifndef NDEBUG
template <class config_t>
void writeback_tmpl_t<config_t>::deadlock_debug() {
    printf("\n----- Writeback -----\n");
    const char *st_name;
    switch(state) {
        case state_none: st_name = "state_none"; break;
        case state_locking: st_name = "state_locking"; break;
        case state_locked: st_name = "state_locked"; break;
        case state_write_bufs: st_name = "state_write_bufs"; break;
        default: st_name = "<invalid state>"; break;
    }
    printf("state = %s\n", st_name);
}
#endif

template <class config_t>
void writeback_tmpl_t<config_t>::local_buf_t::set_dirty(buf_t *super) {
    // 'super' is actually 'this', but as a buf_t* instead of a local_buf_t*
    if(!dirty) {
        // Mark block as dirty if it hasn't been already
        dirty = true;
        writeback->dirty_bufs.push_back(super);
    }
}

template <class config_t>
void writeback_tmpl_t<config_t>::safety_timer_callback(void *ctx) {
    writeback_tmpl_t *self = static_cast<writeback_tmpl_t *>(ctx);
    self->safety_timer = NULL;
    assert(self->state == state_none);
    self->writeback(NULL);
}

template <class config_t>
void writeback_tmpl_t<config_t>::on_lock_available() {
    assert(state == state_locking);
    if (state == state_locking) {
        state = state_locked;
        writeback(NULL);
    }
}

template <class config_t>
void writeback_tmpl_t<config_t>::writeback(buf_t *buf) {
    //printf("Writeback being called, state %d\n", state);

    if (state == state_none) {
        assert(buf == NULL);

        // Cancel the safety timer because we're doing writeback now, so we don't need it to remind
        // us later
        if (safety_timer) {
            get_cpu_context()->event_queue->cancel_timer(safety_timer);
            safety_timer = NULL;
        }

        /* Start a read transaction so we can request bufs. */
        assert(transaction == NULL);
        if (shutdown_callback) // Backdoor around "no new transactions" assert.
            final_sync = true;
        transaction = cache->begin_transaction(rwi_read, NULL);
        final_sync = false;
        assert(transaction != NULL); // Read txns always start immediately.

        /* Request exclusive flush_lock, forcing all write txns to complete. */
        state = state_locking;
        bool locked = flush_lock->lock(rwi_write, this);
        if (locked) {
            state = state_locked;
        }
    }
    if (state == state_locked) {
        assert(buf == NULL);
        assert(flush_bufs.empty());
        assert(flush_txns.empty());

        flush_txns.append_and_clear(&txns);

        /* Request read locks on all of the blocks we need to flush. */
        // TODO: optimize away dynamic allocation
        typename serializer_t::write *writes =
            (typename serializer_t::write*)calloc(dirty_bufs.size(), sizeof *writes);
        int i;
        typename intrusive_list_t<buf_t>::iterator it;
        for (it = dirty_bufs.begin(), i = 0; it != dirty_bufs.end(); it++, i++) {
            buf_t *_buf = &*it;

            // Acquire the blocks
            buf_t *buf = transaction->acquire(_buf->get_block_id(), rwi_read, NULL);
            assert(buf);         // Acquire must succeed since we hold the flush_lock.
            assert(buf == _buf); // Acquire should return the same buf we stored earlier.

            // Fill the serializer structure
            writes[i].block_id = buf->get_block_id();
            writes[i].buf = buf->ptr();
            writes[i].callback = buf;
        }
        flush_bufs.append_and_clear(&dirty_bufs);

        flush_lock->unlock(); // Write transactions can now proceed again.

        /* Start writing all the dirty bufs down, as a transaction. */
        // TODO(NNW): Now that the serializer/aio-system breaks writes up into
        // chunks, we may want to worry about submitting more heavily contended
        // bufs earlier in the process so more write FSMs can proceed sooner.
        if (flush_bufs.size())
            cache->do_write(get_cpu_context()->event_queue, writes,
                            flush_bufs.size());
        free(writes);
        state = state_write_bufs;
    }
    if (state == state_write_bufs) {
        if (buf) {
            flush_bufs.remove(buf);
            buf->set_clean();
            buf->release();
        }
        if (flush_bufs.empty()) {
            /* Notify all waiting transactions of completion. */
            typename intrusive_list_t<txn_state_t>::iterator it;
            for (it = flush_txns.begin(); it != flush_txns.end(); ) {
                txn_state_t *txn_state = &*it;
                it++;
                txn_state->txn->committed(txn_state->callback);
                flush_txns.remove(txn_state);
                delete txn_state;
            }
            assert(flush_txns.empty());

            for (typename std::vector<sync_callback_t*, gnew_alloc<sync_callback_t*> >::iterator it =
                     sync_callbacks.begin(); it != sync_callbacks.end(); ++it)
                (*it)->on_sync();
            sync_callbacks.clear();

            /* Reset all of our state. */
            bool committed __attribute__((unused)) = transaction->commit(NULL);
            assert(committed); // Read-only transactions commit immediately.
            transaction = NULL;
            state = state_none;

            //printf("Writeback complete\n");
        } else {
            //printf("Flush bufs, waiting for %ld more\n", flush_bufs.size());
        }
    }
}

#endif  // __BUFFER_CACHE_WRITEBACK_IMPL_HPP__
<commit_msg>Insignificant rearrangement of writeback_tmpl_t::commit<commit_after>
#ifndef __BUFFER_CACHE_WRITEBACK_IMPL_HPP__
#define __BUFFER_CACHE_WRITEBACK_IMPL_HPP__

template <class config_t>
writeback_tmpl_t<config_t>::writeback_tmpl_t(
        cache_t *cache,
        bool wait_for_flush,
        unsigned int safety_timer_ms,
        unsigned int force_flush_threshold)
    : safety_timer(NULL),
      wait_for_flush(wait_for_flush),
      safety_timer_ms(safety_timer_ms),
      force_flush_threshold(force_flush_threshold),
      cache(cache),
      num_txns(0),
      shutdown_callback(NULL),
      final_sync(NULL),
      state(state_none),
      transaction(NULL) {
}

template <class config_t>
writeback_tmpl_t<config_t>::~writeback_tmpl_t() {
    gdelete(flush_lock);
}

template <class config_t>
void writeback_tmpl_t<config_t>::start() {
    flush_lock =
        gnew<rwi_lock_t>(&get_cpu_context()->event_queue->message_hub,
                         get_cpu_context()->event_queue->queue_id);
}

template <class config_t>
void writeback_tmpl_t<config_t>::shutdown(sync_callback_t *callback) {
    assert(shutdown_callback == NULL);
    shutdown_callback = callback;
    if (!num_txns && state == state_none) // If num_txns, commit() will do this
        sync(callback);
}

template <class config_t>
void writeback_tmpl_t<config_t>::sync(sync_callback_t *callback) {
    sync_callbacks.push_back(callback);
    // Start a new writeback process if one isn't in progress.
    if (state == state_none)
        writeback(NULL);
}

template <class config_t>
bool writeback_tmpl_t<config_t>::begin_transaction(transaction_t *txn) {
    assert(txn->get_access() == rwi_read || txn->get_access() == rwi_write);
    // TODO(NNW): If there's ever any asynchrony between socket reads and
    // begin_transaction, we'll need a better check here.
    assert(shutdown_callback == NULL || final_sync);
    num_txns++;
    if (txn->get_access() == rwi_read)
        return true;
    bool locked = flush_lock->lock(rwi_read, txn);
    return locked;
}

template <class config_t>
bool writeback_tmpl_t<config_t>::commit(transaction_t *txn,
        transaction_commit_callback_t *callback) {

    num_txns --;

    if (txn->get_access() == rwi_write) {
        flush_lock -> unlock();
    }

    if (num_txns == 0 && shutdown_callback != NULL) {
        // All txns shut down, start final sync.
        sync(shutdown_callback);
    }

    if (txn->get_access() == rwi_write && state == state_none) {
        /* At the end of every write transaction, check if the number of dirty blocks exceeds the
        threshold to force writeback to start. */
        if (num_dirty_blocks() > force_flush_threshold) {
            writeback(NULL);
        }
        /* Otherwise, start the safety timer so that the modified data doesn't sit in memory for too
        long without being written to disk. */
        else if (!safety_timer && safety_timer_ms != NEVER_FLUSH) {
            safety_timer = get_cpu_context()->event_queue->
                fire_timer_once(safety_timer_ms, safety_timer_callback, this);
        }
    }

    if (txn->get_access() == rwi_write && wait_for_flush) {
        txns.push_back(new txn_state_t(txn, callback));
        return false;
    } else {
        return true;
    }
}

template <class config_t>
void writeback_tmpl_t<config_t>::aio_complete(buf_t *buf, bool written) {
    if (written)
        writeback(buf);
}

template <class config_t>
unsigned int writeback_tmpl_t<config_t>::num_dirty_blocks() {
    return dirty_bufs.size();
}

#ifndef NDEBUG
template <class config_t>
void writeback_tmpl_t<config_t>::deadlock_debug() {
    printf("\n----- Writeback -----\n");
    const char *st_name;
    switch(state) {
        case state_none: st_name = "state_none"; break;
        case state_locking: st_name = "state_locking"; break;
        case state_locked: st_name = "state_locked"; break;
        case state_write_bufs: st_name = "state_write_bufs"; break;
        default: st_name = "<invalid state>"; break;
    }
    printf("state = %s\n", st_name);
}
#endif

template <class config_t>
void writeback_tmpl_t<config_t>::local_buf_t::set_dirty(buf_t *super) {
    // 'super' is actually 'this', but as a buf_t* instead of a local_buf_t*
    if(!dirty) {
        // Mark block as dirty if it hasn't been already
        dirty = true;
        writeback->dirty_bufs.push_back(super);
    }
}

template <class config_t>
void writeback_tmpl_t<config_t>::safety_timer_callback(void *ctx) {
    writeback_tmpl_t *self = static_cast<writeback_tmpl_t *>(ctx);
    self->safety_timer = NULL;
    assert(self->state == state_none);
    self->writeback(NULL);
}

template <class config_t>
void writeback_tmpl_t<config_t>::on_lock_available() {
    assert(state == state_locking);
    if (state == state_locking) {
        state = state_locked;
        writeback(NULL);
    }
}

template <class config_t>
void writeback_tmpl_t<config_t>::writeback(buf_t *buf) {
    //printf("Writeback being called, state %d\n", state);

    if (state == state_none) {
        assert(buf == NULL);

        // Cancel the safety timer because we're doing writeback now, so we don't need it to remind
        // us later
        if (safety_timer) {
            get_cpu_context()->event_queue->cancel_timer(safety_timer);
            safety_timer = NULL;
        }

        /* Start a read transaction so we can request bufs. */
        assert(transaction == NULL);
        if (shutdown_callback) // Backdoor around "no new transactions" assert.
            final_sync = true;
        transaction = cache->begin_transaction(rwi_read, NULL);
        final_sync = false;
        assert(transaction != NULL); // Read txns always start immediately.

        /* Request exclusive flush_lock, forcing all write txns to complete. */
        state = state_locking;
        bool locked = flush_lock->lock(rwi_write, this);
        if (locked) {
            state = state_locked;
        }
    }
    if (state == state_locked) {
        assert(buf == NULL);
        assert(flush_bufs.empty());
        assert(flush_txns.empty());

        flush_txns.append_and_clear(&txns);

        /* Request read locks on all of the blocks we need to flush. */
        // TODO: optimize away dynamic allocation
        typename serializer_t::write *writes =
            (typename serializer_t::write*)calloc(dirty_bufs.size(), sizeof *writes);
        int i;
        typename intrusive_list_t<buf_t>::iterator it;
        for (it = dirty_bufs.begin(), i = 0; it != dirty_bufs.end(); it++, i++) {
            buf_t *_buf = &*it;

            // Acquire the blocks
            buf_t *buf = transaction->acquire(_buf->get_block_id(), rwi_read, NULL);
            assert(buf);         // Acquire must succeed since we hold the flush_lock.
            assert(buf == _buf); // Acquire should return the same buf we stored earlier.

            // Fill the serializer structure
            writes[i].block_id = buf->get_block_id();
            writes[i].buf = buf->ptr();
            writes[i].callback = buf;
        }
        flush_bufs.append_and_clear(&dirty_bufs);

        flush_lock->unlock(); // Write transactions can now proceed again.

        /* Start writing all the dirty bufs down, as a transaction. */
        // TODO(NNW): Now that the serializer/aio-system breaks writes up into
        // chunks, we may want to worry about submitting more heavily contended
        // bufs earlier in the process so more write FSMs can proceed sooner.
        if (flush_bufs.size())
            cache->do_write(get_cpu_context()->event_queue, writes,
                            flush_bufs.size());
        free(writes);
        state = state_write_bufs;
    }
    if (state == state_write_bufs) {
        if (buf) {
            flush_bufs.remove(buf);
            buf->set_clean();
            buf->release();
        }
        if (flush_bufs.empty()) {
            /* Notify all waiting transactions of completion. */
            typename intrusive_list_t<txn_state_t>::iterator it;
            for (it = flush_txns.begin(); it != flush_txns.end(); ) {
                txn_state_t *txn_state = &*it;
                it++;
                txn_state->txn->committed(txn_state->callback);
                flush_txns.remove(txn_state);
                delete txn_state;
            }
            assert(flush_txns.empty());

            for (typename std::vector<sync_callback_t*, gnew_alloc<sync_callback_t*> >::iterator it =
                     sync_callbacks.begin(); it != sync_callbacks.end(); ++it)
                (*it)->on_sync();
            sync_callbacks.clear();

            /* Reset all of our state. */
            bool committed __attribute__((unused)) = transaction->commit(NULL);
            assert(committed); // Read-only transactions commit immediately.
            transaction = NULL;
            state = state_none;

            //printf("Writeback complete\n");
        } else {
            //printf("Flush bufs, waiting for %ld more\n", flush_bufs.size());
        }
    }
}

#endif  // __BUFFER_CACHE_WRITEBACK_IMPL_HPP__
<|endoftext|>


<commit_before>/*
 * Part of HTTPP.
 *
 * Distributed under the 3-clause BSD licence (See LICENCE.TXT file at the
 * project root).
 *
 * Copyright (c) 2014 Thomas Sanchez.  All rights reserved.
 *
 */

#include "Manager.hpp"

#include <exception>
#include <stdexcept>
#include <atomic>
#include <mutex>
#include <functional>

#include "Connection.hpp"

static std::once_flag curl_init_flag;
static void init_curl()
{
    if (curl_global_init(CURL_GLOBAL_ALL) != 0)
    {
        throw std::runtime_error("Cannot initialize curl");
    }
}

namespace HTTPP
{
namespace HTTP
{
namespace client
{
namespace detail
{

Manager::Manager(UTILS::ThreadPool& pool)
: handler(nullptr)
, pool(pool)
, strand(pool.getService())
, timer(pool.getService())
{
    std::call_once(curl_init_flag, &init_curl);
    handler = curl_multi_init();
    if (!handler)
    {
        throw std::runtime_error("Cannot initialize curl multi handle");
    }

    manager_setopt(CURLMOPT_SOCKETFUNCTION, &sock_cb);
    manager_setopt(CURLMOPT_SOCKETDATA, this);
    manager_setopt(CURLMOPT_TIMERFUNCTION, &curl_timer_cb);
    manager_setopt(CURLMOPT_TIMERDATA, this);
}

Manager::~Manager()
{
    if (handler)
    {
        curl_multi_cleanup(handler);
    }
}

void Manager::timer_cb(const boost::system::error_code& error)
{
    if (!error)
    {
        int still_running = 0;
        auto rc = curl_multi_socket_action(
            handler, CURL_SOCKET_TIMEOUT, 0, &still_running);

        if (rc != CURLM_OK)
        {
            BOOST_LOG_TRIVIAL(error)
                << "Error curl multi: " << curl_multi_strerror(rc);
            throw std::runtime_error("timer_cb error");
        }

        checkHandles();
    }
}

int Manager::curl_timer_cb(CURLM*, long timeout_ms, void* userdata)
{
    Manager* manager = (Manager*)userdata;

    manager->timer.cancel();

    if (timeout_ms > 0)
    {
        manager->timer.expires_from_now(boost::posix_time::millisec(timeout_ms));
        manager->timer.async_wait(
            std::bind(&Manager::timer_cb, manager, std::placeholders::_1));
    }
    else
    {
        boost::system::error_code error; /*success*/
        manager->timer_cb(error);
    }

    return 0;
}

int Manager::sock_cb(CURL* easy,
                     curl_socket_t s,
                     int what,
                     void* multi_private,
                     void* socket_private)
{
    Manager* manager = (Manager*)multi_private;

    if (what == CURL_POLL_REMOVE)
    {
        return 0;
    }

    if (!socket_private)
    {
        void* v = nullptr;
        auto rc = curl_easy_getinfo(easy, CURLINFO_PRIVATE, &v);
        if (rc != CURLE_OK)
        {
            throw std::runtime_error("Cannot get private info:" +
                                     std::string(curl_easy_strerror(rc)));
        }

        curl_multi_assign(manager->handler, s, v);
        socket_private = v;
    }

    Connection* connection = (Connection*)socket_private;
    connection->poll_action = what;
    manager->poll(connection, what);
    return 0;
}

void Manager::checkHandles()
{
    CURLMsg* msg;
    int msgs_left = 0;
    while ((msg = curl_multi_info_read(handler, &msgs_left)))
    {
        if (msg->msg == CURLMSG_DONE)
        {
            auto easy = msg->easy_handle;
            auto result = msg->data.result;

            Connection* conn;
            curl_easy_getinfo(easy, CURLINFO_PRIVATE, &conn);
            conn->poll_action = 0;
            auto rc = curl_multi_remove_handle(handler, easy);

            if (rc != CURLM_OK)
            {
                BOOST_LOG_TRIVIAL(error) << "Cannot unregister easy handle";
            }

            pool.post([result, conn, easy, this]
                      { conn->buildResponse(result); });
        }
    }
}

void Manager::performOp(Connection* connection, int action)
{
    int still_running = 0;

    auto rc = curl_multi_socket_action(
        handler, connection->socket.native_handle(), action, &still_running);
    if (rc != CURLM_OK)
    {
        auto exc = std::make_exception_ptr(std::runtime_error(curl_multi_strerror(rc)));
        connection->complete(exc);
        std::rethrow_exception(exc);
    }

    checkHandles();

    if (still_running <= 0)
    {
        timer.cancel();
    }
    else
    {
        if (action == connection->poll_action)
        {
            poll(connection, connection->poll_action);
        }
    }
}

void Manager::poll(Connection* connection, int action)
{
    boost::asio::ip::tcp::socket& tcp_socket = connection->socket;

    if (action == CURL_POLL_IN)
    {
        tcp_socket.async_read_some(
            boost::asio::null_buffers(),
            strand.wrap(std::bind(&Manager::performOp, this, connection, action)));
    }
    else if (action == CURL_POLL_OUT)
    {
        tcp_socket.async_write_some(
            boost::asio::null_buffers(),
            strand.wrap(std::bind(&Manager::performOp, this, connection, action)));
    }
    else if (action == CURL_POLL_INOUT)
    {
        tcp_socket.async_read_some(
            boost::asio::null_buffers(),
            strand.wrap(std::bind(&Manager::performOp, this, connection, action)));

        tcp_socket.async_write_some(
            boost::asio::null_buffers(),
            strand.wrap(std::bind(&Manager::performOp, this, connection, action)));
    }
    else
    {
        connection->complete(std::make_exception_ptr(
            std::runtime_error("Unknow poll operation requested")));
    }
}

void Manager::handleRequest(Method method, Connection::ConnectionPtr connection)
{

    Connection* conn = connection.release();

    strand.post([this, method, conn]()
                {
                    try
                    {
                        conn->configureRequest(method);
                    }
                    catch (...)
                    {
                        conn->complete(std::current_exception());
                        return;
                    }

                    auto rc = curl_multi_add_handle(handler, conn->handle);
                    if (rc != CURLM_OK)
                    {
                        std::string message = curl_multi_strerror(rc);
                        BOOST_LOG_TRIVIAL(error)
                            << "Error scheduling a new request: " << message;
                        conn->complete(std::make_exception_ptr(
                            std::runtime_error(message)));
                    }
                });
}

} // namespace detail
} // namespace client
} // namespace HTTP
} // namespace HTTPP
<commit_msg>Cancel timer on manager destruction + protect the timeout cb<commit_after>/*
 * Part of HTTPP.
 *
 * Distributed under the 3-clause BSD licence (See LICENCE.TXT file at the
 * project root).
 *
 * Copyright (c) 2014 Thomas Sanchez.  All rights reserved.
 *
 */

#include "Manager.hpp"

#include <exception>
#include <stdexcept>
#include <atomic>
#include <mutex>
#include <functional>

#include "Connection.hpp"

static std::once_flag curl_init_flag;
static void init_curl()
{
    if (curl_global_init(CURL_GLOBAL_ALL) != 0)
    {
        throw std::runtime_error("Cannot initialize curl");
    }
}

namespace HTTPP
{
namespace HTTP
{
namespace client
{
namespace detail
{

Manager::Manager(UTILS::ThreadPool& pool)
: handler(nullptr)
, pool(pool)
, strand(pool.getService())
, timer(pool.getService())
{
    std::call_once(curl_init_flag, &init_curl);
    handler = curl_multi_init();
    if (!handler)
    {
        throw std::runtime_error("Cannot initialize curl multi handle");
    }

    manager_setopt(CURLMOPT_SOCKETFUNCTION, &sock_cb);
    manager_setopt(CURLMOPT_SOCKETDATA, this);
    manager_setopt(CURLMOPT_TIMERFUNCTION, &curl_timer_cb);
    manager_setopt(CURLMOPT_TIMERDATA, this);
}

Manager::~Manager()
{
    if (handler)
    {
        curl_multi_cleanup(handler);
    }
    timer.cancel();
}

void Manager::timer_cb(const boost::system::error_code& error)
{
    if (!error)
    {
        int still_running = 0;
        auto rc = curl_multi_socket_action(
            handler, CURL_SOCKET_TIMEOUT, 0, &still_running);

        if (rc != CURLM_OK)
        {
            BOOST_LOG_TRIVIAL(error)
                << "Error curl multi: " << curl_multi_strerror(rc);
            throw std::runtime_error("timer_cb error");
        }

        checkHandles();
    }
}

int Manager::curl_timer_cb(CURLM*, long timeout_ms, void* userdata)
{
    Manager* manager = (Manager*)userdata;

    manager->timer.cancel();

    if (timeout_ms > 0)
    {
        manager->timer.expires_from_now(boost::posix_time::millisec(timeout_ms));
        manager->timer.async_wait(manager->strand.wrap(
            std::bind(&Manager::timer_cb, manager, std::placeholders::_1)));
    }
    else
    {
        boost::system::error_code error; /*success*/
        manager->timer_cb(error);
    }

    return 0;
}

int Manager::sock_cb(CURL* easy,
                     curl_socket_t s,
                     int what,
                     void* multi_private,
                     void* socket_private)
{
    Manager* manager = (Manager*)multi_private;

    if (what == CURL_POLL_REMOVE)
    {
        return 0;
    }

    if (!socket_private)
    {
        void* v = nullptr;
        auto rc = curl_easy_getinfo(easy, CURLINFO_PRIVATE, &v);
        if (rc != CURLE_OK)
        {
            throw std::runtime_error("Cannot get private info:" +
                                     std::string(curl_easy_strerror(rc)));
        }

        curl_multi_assign(manager->handler, s, v);
        socket_private = v;
    }

    Connection* connection = (Connection*)socket_private;
    connection->poll_action = what;
    manager->poll(connection, what);
    return 0;
}

void Manager::checkHandles()
{
    CURLMsg* msg;
    int msgs_left = 0;
    while ((msg = curl_multi_info_read(handler, &msgs_left)))
    {
        if (msg->msg == CURLMSG_DONE)
        {
            auto easy = msg->easy_handle;
            auto result = msg->data.result;

            Connection* conn;
            curl_easy_getinfo(easy, CURLINFO_PRIVATE, &conn);
            conn->poll_action = 0;
            auto rc = curl_multi_remove_handle(handler, easy);

            if (rc != CURLM_OK)
            {
                BOOST_LOG_TRIVIAL(error) << "Cannot unregister easy handle";
            }

            pool.post([result, conn, easy, this]
                      { conn->buildResponse(result); });
        }
    }
}

void Manager::performOp(Connection* connection, int action)
{
    int still_running = 0;

    auto rc = curl_multi_socket_action(
        handler, connection->socket.native_handle(), action, &still_running);
    if (rc != CURLM_OK)
    {
        auto exc = std::make_exception_ptr(std::runtime_error(curl_multi_strerror(rc)));
        connection->complete(exc);
        std::rethrow_exception(exc);
    }

    checkHandles();

    if (still_running <= 0)
    {
        timer.cancel();
    }
    else
    {
        if (action == connection->poll_action)
        {
            poll(connection, connection->poll_action);
        }
    }
}

void Manager::poll(Connection* connection, int action)
{
    boost::asio::ip::tcp::socket& tcp_socket = connection->socket;

    if (action == CURL_POLL_IN)
    {
        tcp_socket.async_read_some(
            boost::asio::null_buffers(),
            strand.wrap(std::bind(&Manager::performOp, this, connection, action)));
    }
    else if (action == CURL_POLL_OUT)
    {
        tcp_socket.async_write_some(
            boost::asio::null_buffers(),
            strand.wrap(std::bind(&Manager::performOp, this, connection, action)));
    }
    else if (action == CURL_POLL_INOUT)
    {
        tcp_socket.async_read_some(
            boost::asio::null_buffers(),
            strand.wrap(std::bind(&Manager::performOp, this, connection, action)));

        tcp_socket.async_write_some(
            boost::asio::null_buffers(),
            strand.wrap(std::bind(&Manager::performOp, this, connection, action)));
    }
    else
    {
        connection->complete(std::make_exception_ptr(
            std::runtime_error("Unknow poll operation requested")));
    }
}

void Manager::handleRequest(Method method, Connection::ConnectionPtr connection)
{

    Connection* conn = connection.release();

    strand.post([this, method, conn]()
                {
                    try
                    {
                        conn->configureRequest(method);
                    }
                    catch (...)
                    {
                        conn->complete(std::current_exception());
                        return;
                    }

                    auto rc = curl_multi_add_handle(handler, conn->handle);
                    if (rc != CURLM_OK)
                    {
                        std::string message = curl_multi_strerror(rc);
                        BOOST_LOG_TRIVIAL(error)
                            << "Error scheduling a new request: " << message;
                        conn->complete(std::make_exception_ptr(
                            std::runtime_error(message)));
                    }
                });
}

} // namespace detail
} // namespace client
} // namespace HTTP
} // namespace HTTPP
<|endoftext|>


<commit_before>#include "sto3g.hpp"
//
//
//
void lcao_wavefunction::sto3g::build_kinetic_matrix()
{
//
    t_matrix.array::create_array(number_of_atoms, number_of_atoms);
    t_matrix.array::set_config(*config);
    t_matrix.array::set_name("Kinetic energy matrix");
//
    double t_integral = 0.0, ij_distance = 0.0, a = 0.0, b = 0.0, c = 0.0, d = 0.0, e = 0.0, f = 0.0;
    unsigned int i_type = 0, i_atom = 0;
    #pragma omp parallel for private(i_atom, i_type, ij_distance, a, b, c, d, e, f) reduction(+:t_integral) ordered schedule(dynamic)
    for(i_atom = 1; i_atom <= number_of_atoms; i_atom++)
    {
        i_type = type -> get(i_atom);
        unsigned int j_atom = 0, j_type = 0;
        #pragma omp parallel for private(j_atom, j_type, ij_distance, a, b, c, d, e, f) reduction(+:t_integral) ordered schedule(dynamic)
        for(j_atom = i_atom; j_atom <= number_of_atoms; j_atom++)
        {
            j_type = type -> get(j_atom);
            ij_distance = (i_atom == j_atom? 0.0 : interatomic_distance(i_atom, j_atom));
            unsigned int m_primitive = 0;
            #pragma omp parallel for private(m_primitive, a, b, c, d, e, f) reduction(+:t_integral) ordered schedule(dynamic)
            for(m_primitive = 1; m_primitive <= (i_type == 1? 3:6); m_primitive++)
            {
                unsigned int n_primitive = 0;
                #pragma omp parallel for private(n_primitive, a, b, c, d, e, f) reduction(+:t_integral) ordered schedule(dynamic)
                for(n_primitive = 1; n_primitive <= (i_type == 1? 3:6); n_primitive++)
                {
                    a = exp(i_type, m_primitive) + exp(j_type, n_primitive);
                    #pragma omp parallel sections num_threads(5)
                    {
                        #pragma omp section
                        {
                            b = coeff(i_type, m_primitive)*coeff(j_type, n_primitive);
                        }
                        #pragma omp section
                        {
                            c = exp(i_type, m_primitive)*exp(j_type, n_primitive)/a;
                        }
                        #pragma omp section
                        {
                            d = 3.0 - 2.0*exp(i_type, m_primitive)*exp(j_type, n_primitive)*gsl_pow_2(ij_distance)/a;
                        }
                        #pragma omp section
                        {
                            e = pow(M_PI/a, 1.5);
                        }
                        #pragma omp section
                        {
                            f = gf_product_const(exp(i_type, m_primitive), exp(j_type, n_primitive), ij_distance);
                        }
                    }
//
//                  A. Szabo and N. Ostlund;
//                  Modern Quantum Chemistry - Introduction to Advanced Electronic Sctructure;
//                  Appendix A;
//                  pag. 412;
//                  equation (A.11):
                    #pragma omp atomic
                    t_integral += b*c*d*e*f;
//
                    a = b = c = d = e = f = 0.0;
                } // for(n_primitive)
            } // for(m_primitive)
            t_matrix.array::set(i_atom, j_atom, t_integral);
            t_matrix.array::set(j_atom, i_atom, t_integral);
            t_integral = ij_distance = 0.0;
        } // for(j_atom)
    } // for(i_atom)
}
<commit_msg>Delete sto3g__build_kinetic_matrix.cpp<commit_after><|endoftext|>


<commit_before>//Setting alphanumeric labels in a 1-d histogram
//Author; Rene Brun
void labels1()
{
   const Int_t nx = 20;
   char *people[nx] = {"Jean","Pierre","Marie","Odile","Sebastien","Fons","Rene",
      "Nicolas","Xavier","Greg","Bjarne","Anton","Otto","Eddy","Peter","Pasha",
      "Philippe","Suzanne","Jeff","Valery"};
   TCanvas *c1 = new TCanvas("c1","demo bin labels",10,10,900,500);
   c1->SetGrid();
   c1->SetBottomMargin(0.15);
   TH1F *h = new TH1F("h","test",nx,0,nx);
   h->SetFillColor(38);
   for (Int_t i=0;i<5000;i++) {
      h->Fill(gRandom->Gaus(0.5*nx,0.2*nx));
   }
   h->SetStats(0);
   for (i=1;i<=nx;i++) {
      h->GetXaxis()->SetBinLabel(i,people[i-1]);
   }
   h->Draw();
   TPaveText *pt = new TPaveText(0.6,0.7,0.98,0.98,"brNDC");
   pt->SetFillColor(18);
   pt->SetTextAlign(12);
   pt->AddText("Use the axis Context Menu LabelsOption");
   pt->AddText(" \"a\"   to sort by alphabetic order");
   pt->AddText(" \">\"   to sort by decreasing vakues");
   pt->AddText(" \"<\"   to sort by increasing vakues");
   pt->Draw();
}
<commit_msg>Fix typos<commit_after>//Setting alphanumeric labels in a 1-d histogram
//Author; Rene Brun
void labels1()
{
   const Int_t nx = 20;
   char *people[nx] = {"Jean","Pierre","Marie","Odile","Sebastien","Fons","Rene",
      "Nicolas","Xavier","Greg","Bjarne","Anton","Otto","Eddy","Peter","Pasha",
      "Philippe","Suzanne","Jeff","Valery"};
   TCanvas *c1 = new TCanvas("c1","demo bin labels",10,10,900,500);
   c1->SetGrid();
   c1->SetBottomMargin(0.15);
   TH1F *h = new TH1F("h","test",nx,0,nx);
   h->SetFillColor(38);
   for (Int_t i=0;i<5000;i++) {
      h->Fill(gRandom->Gaus(0.5*nx,0.2*nx));
   }
   h->SetStats(0);
   for (i=1;i<=nx;i++) {
      h->GetXaxis()->SetBinLabel(i,people[i-1]);
   }
   h->Draw();
   TPaveText *pt = new TPaveText(0.6,0.7,0.98,0.98,"brNDC");
   pt->SetFillColor(18);
   pt->SetTextAlign(12);
   pt->AddText("Use the axis Context Menu LabelsOption");
   pt->AddText(" \"a\"   to sort by alphabetic order");
   pt->AddText(" \">\"   to sort by decreasing values");
   pt->AddText(" \"<\"   to sort by increasing values");
   pt->Draw();
}
<|endoftext|>


<commit_before>/*
 * Worldvisions Weaver Software:
 *   Copyright (C) 1997, 1998, 1999 Worldvisions Computer Technology, Inc.
 *
 * Intelligent serial port scanner: try to find a port (or ports)
 * with a working modem, guess a basic startup init string, and find
 * the maximum baud rate.
 */
#include "wvmodemscan.h"
#include "wvmodem.h"
#include "strutils.h"
#include <time.h>
#include <assert.h>
#include <dirent.h>
#include <ctype.h>
#include <sys/stat.h>

// startup at atz atq0 atv1 ate1 ats0 carrier dtr fastdial
// baudstep reinit done
static char *commands[WvModemScan::NUM_STAGES] = {
    NULL, "Q0 V1 E1", "Z", "S0=0",
    "&C1", "&D2", "S11=55", "+FCLASS=0", NULL,
    NULL, "", NULL
};

WvModemScan::WvModemScan(const char *devname)
	: debug(devname, WvLog::Debug)
{
    stage = Startup;
    memset(status, 0, sizeof(status));

    if (devname[0] == '/')
	file = devname;
    else
	file = WvString("/dev/%s", devname);

    baud = 1200;
    modem = NULL;
    tries = 0;
    broken = false;
}

WvModemScan::~WvModemScan()
{
    if (isok() && isdone())
	debug(WvLog::Info, "Speed %s; init \"%s\"\n", maxbaud(), initstr());

    if (modem)
	delete modem;
}

bool WvModemScan::isok() const
{
    return !broken;
}

WvString WvModemScan::initstr() const
{
    char s[200];

    strcpy(s, "AT");

    for (int i = 0; i < NUM_STAGES; i++)
    {
	if (status[i] != Worked && status[i] != Test)
	    continue;
	if (!commands[i] || !commands[i][0])
	    continue;
	if ((commands[i][0]=='Z' || commands[i][0]=='I') && status[i] != Test)
	    continue;

	strcat(s, commands[i]);
	strcat(s, " ");
    }

    return WvString(trim_string(s)).unique();
}

void WvModemScan::execute()
{
    if (isdone() || !isok()) return;

    switch ((Stage)stage)
    {
    case Startup:
	assert(!modem);
	modem = new WvModem(file, baud);
	modem->die_fast = true;
	if (!modem->isok())
	{
	    if (modem->geterr()
		&& modem->geterr() != EIO
		&& modem->geterr() != ENOENT
		&& modem->geterr() != ENODEV)
	    {
		debug(WvLog::Info, "%s\n", modem->errstr());
	    }
	    broken = true;
	}
	else
	    stage++;
	break;

    case AT:
    case ATZ:
    case ATS0:
    case Carrier:
    case DTR:
    case FastDial:
    case FCLASS:
    case Reinit:
	assert(modem);
	status[stage] = Test;
	if ( !doresult(WvString("%s\r", initstr()), stage==ATZ ? 3000 : 500)
	    || ((stage <= ATZ || stage == Reinit) && status[stage]==Fail) )
	{
	    tries++;

	    if (tries >= 3)
	    {
		debug("nothing.\n");
		broken = true;
	    }

	    // else try again shortly
	}
	else
	{
	    tries = 0;
	    stage++;
	}
	break;

    case GetIdent:
	assert(modem);
	status[stage] = Test;
	debug("Modem Identifier: ");
	if ( !doresult(WvString("ATI\r"), 500) || (status[stage]==Fail) )
	{
	    tries++;

	    if (tries >= 3)
	    	debug("nothing.\n");

	    // else try again shortly
	}
	else
	{
	    if (is_isdn())
	    	debug("Looks like an ISDN modem.\n");
	    tries = 0;
	    stage++;
	}

    case BaudStep:
	assert(modem);
	modem->drain();
	modem->speed(baud*2);

	// if we try 2*baud five times without success, or setting 2*baud
	// results in a lower setting than 1*baud, we have reached the
	// top speed of the modem or the serial port, respectively.
	if (tries >= 3 || modem->speed() < baud)
	{
	    // using the absolute maximum baud rate confuses many modems
	    // in obscure ways; step down one.
	    modem->speed(baud);
	    debug("Max speed is %s; ", modem->speed());
	    if (is_isdn())
	    {
	    	//if (modem->speed() != 230400)		// FIXME
	    	    modem->speed(115200);
	    	baud = modem->speed();
	    	debug ("using %s for ISDN modem.\n", baud);
	    }
	    else
	    {
		modem->speed(baud / 2);
		baud = modem->speed(); // get correct value!
		debug("using %s to be safe.\n", baud);
	    }

	    stage++;
	    status[stage] = Worked;
	    break;
	}

	debug("Speed %s: ", modem->speed());

	if (!doresult("AT\r", 500) || status[stage] == Fail)
	{
	    tries++;
	}
	else // got a response
	{
	    baud *= 2;
	    tries = 0;
	    // next time through we try a faster speed
	}
	break;

    case Done:
    case NUM_STAGES:
	assert(0);
	break; // should never happen
    }

    if (stage == Done) // we just incremented stage number to Done
    {
	if (modem)
	    delete modem;
	modem = NULL;
    }
}

bool WvModemScan::doresult(const WvString &_s, int msec)
{
    char buf[1024], *cptr;
    size_t len;
    WvString s(_s);

    modem->drain();
    usleep(50 * 1000); // delay a bit after emptying the buffer
    modem->write(s);

    debug("%s -- ", trim_string(s.edit()));

    len = coagulate(buf, sizeof(buf), msec);

    if (!len)
    {
	// debug("(no answer yet)\n");
	return false;
    }

    buf[len] = 0;

    cptr = trim_string(buf);
    while (strchr(cptr, '\r'))
    {
	cptr = trim_string(strchr(cptr, '\r'));
	if (stage == GetIdent && status[stage] == Test)
	{
	    char *p = strpbrk(cptr, "\n\r");
	    if (p) *p=0;
	    identifier = cptr;
	    status[stage] = Worked;
	    debug("%s\n", identifier);
	    return true;
	}
    }
    while (strchr(cptr, '\n'))
	cptr = trim_string(strchr(cptr, '\n'));

    debug("%s\n", cptr);

    if (!strncmp(cptr, "OK", 2))
	status[stage] = Worked;
    else
	status[stage] = Fail;

    return true;
}

size_t WvModemScan::coagulate(char *buf, size_t size, int msec)
{
    size_t len = 0, amt;
    char *cptr = buf;

    assert(modem);

    if (!modem->isok())
    {
	broken = true;
	return 0;
    }

    while (modem->select(msec))
    {
	amt = modem->read(cptr, size-1);
	cptr[amt] = 0;

	len += amt;
	size -= amt;
	cptr += amt;

	if (strstr(buf, "OK") || strstr(buf, "ERROR"))
	    break;
    }

    return len;
}

const char *WvModemScan::is_isdn() const
{
    if (!identifier)
    	return NULL;

    if (identifier == "3C882")		// 3Com Impact IQ
    	return identifier;
    if (identifier == "960")		// Motorola BitSurfr
    	return identifier;

    return NULL;
}

static int fileselect(const struct dirent *e)
{
    return !strncmp(e->d_name, "ttyS", 4);     // serial
       // (no internal ISDN support)   || !strncmp(e->d_name, "ttyI", 4);
}

static int filesort(const void *_e1, const void *_e2)
{
    dirent const * const *e1 = (dirent const * const *)_e1;
    dirent const * const *e2 = (dirent const * const *)_e2;
    const char *p1, *p2;
    int diff;

    for (p1=(*e1)->d_name, p2=(*e2)->d_name; *p1 || *p2; p1++, p2++)
    {
	if (!isdigit(*p1) || !isdigit(*p2))
	{
	    diff = *p1 - *p2;
	    if (diff) return diff;
	}
	else // both are digits
	{
	    return atoi(p1) - atoi(p2);
	}
    }

    return 0;
}

void WvModemScanList::setup()
{
    struct dirent **namelist;
    struct stat mouse;
    int num, count, statresponse;

    log = new WvLog("Port Scan", WvLog::Debug);
    thisline = -1;
    printed = false;

    statresponse = stat("/dev/mouse", &mouse);
    num = scandir("/dev", &namelist, fileselect, filesort);

    if (num < 0)
	return;

    for (count = 0; count < num; count++)
    {
	// never search the device assigned to /dev/mouse; most mouse-using
	// programs neglect to lock the device, so we could mess up the
	// mouse response!  (We are careful to put things back when done,
	// but X seems to still get confused.)  Anyway the mouse is seldom
	// a modem.
	if (statresponse==0 && mouse.st_ino == (ino_t)namelist[count]->d_ino)
	{
	    log->print("\nIgnoring %s because /dev/mouse is a link to it.\n",
		       namelist[count]->d_name);
	    continue;
	}

	append(new WvModemScan(WvString("%s", namelist[count]->d_name)),
	       true);
    }

    while (--num >= 0)
	free(namelist[num]);
    free(namelist);
}

void WvModemScanList::shutdown()
{
    delete log;
}

// we used to try to scan all ports simultaneously; unfortunately, this
// caused problems when people had "noncritical" IRQ conflicts (ie. two
// serial ports with the same IRQ, but they work as long as only one port
// is used at a time).  Also, the log messages looked really confused.
//
// So now we do the scanning sequentially, which is slower.  The port
// being scanned is at the head of the list.  If the probe fails, we
// unlink the element.  If it succeeds, we have found a modem -- so,
// isdone() knows we are done when the _first_ element is done.
//
void WvModemScanList::execute()
{
    assert (!isdone());

    WvModemScanList::Iter i(*this);

    for (i.rewind(); i.next(); )
	if (!i().isdone()) break;

    if (!i.cur()) return;

    WvModemScan &s(i);

    if (!s.isok())
    {
	if (!printed)
	{
	    const WvString &f = s.filename();
	    const char *cptr = strrchr(f, '/');
	    if (cptr)
		cptr++;
	    else
		cptr = f;

	    if (!strncmp(cptr, "tty", 3))
		cptr += 3;

	    ++thisline %= 8;
	    if (!thisline)
		log->print("\n");

	    log->print("%-4s ", cptr);
	}

	i.unlink();
	printed = false;
    }
    else
    {
	s.execute();

	if (s.isok())
	    printed = true;
    }

    if (isdone())
	log->write("\n", 1);
}

bool WvModemScanList::isdone()
{
    WvModemScanList::Iter i(*this);

    for (i.rewind(); i.next(); )
	if (!i().isdone()) return false;

    return true;
}
<commit_msg>Patch from Michale K. Johnson <johnsonm@redhat.com> to fix a bug with baud rate detection in wvdialconf; we also now detect modems on /dev/modem.<commit_after>/*
 * Worldvisions Weaver Software:
 *   Copyright (C) 1997, 1998, 1999 Worldvisions Computer Technology, Inc.
 *
 * Intelligent serial port scanner: try to find a port (or ports)
 * with a working modem, guess a basic startup init string, and find
 * the maximum baud rate.
 */
#include "wvmodemscan.h"
#include "wvmodem.h"
#include "strutils.h"
#include <time.h>
#include <assert.h>
#include <dirent.h>
#include <ctype.h>
#include <sys/stat.h>

// startup at atz atq0 atv1 ate1 ats0 carrier dtr fastdial
// baudstep reinit done
static char *commands[WvModemScan::NUM_STAGES] = {
    NULL, "Q0 V1 E1", "Z", "S0=0",
    "&C1", "&D2", "S11=55", "+FCLASS=0", NULL,
    NULL, "", NULL
};

WvModemScan::WvModemScan(const char *devname)
	: debug(devname, WvLog::Debug)
{
    stage = Startup;
    memset(status, 0, sizeof(status));

    if (devname[0] == '/')
	file = devname;
    else
	file = WvString("/dev/%s", devname);

    baud = 1200;
    modem = NULL;
    tries = 0;
    broken = false;
}

WvModemScan::~WvModemScan()
{
    if (isok() && isdone())
	debug(WvLog::Info, "Speed %s; init \"%s\"\n", maxbaud(), initstr());

    if (modem)
	delete modem;
}

bool WvModemScan::isok() const
{
    return !broken;
}

WvString WvModemScan::initstr() const
{
    char s[200];

    strcpy(s, "AT");

    for (int i = 0; i < NUM_STAGES; i++)
    {
	if (status[i] != Worked && status[i] != Test)
	    continue;
	if (!commands[i] || !commands[i][0])
	    continue;
	if ((commands[i][0]=='Z' || commands[i][0]=='I') && status[i] != Test)
	    continue;

	strcat(s, commands[i]);
	strcat(s, " ");
    }

    return WvString(trim_string(s)).unique();
}

void WvModemScan::execute()
{
    if (isdone() || !isok()) return;

    switch ((Stage)stage)
    {
    case Startup:
	assert(!modem);
	modem = new WvModem(file, baud);
	modem->die_fast = true;
	if (!modem->isok())
	{
	    if (modem->geterr()
		&& modem->geterr() != EIO
		&& modem->geterr() != ENOENT
		&& modem->geterr() != ENODEV)
	    {
		debug(WvLog::Info, "%s\n", modem->errstr());
	    }
	    broken = true;
	}
	else
	    stage++;
	break;

    case AT:
    case ATZ:
    case ATS0:
    case Carrier:
    case DTR:
    case FastDial:
    case FCLASS:
    case Reinit:
	assert(modem);
	status[stage] = Test;
	if ( !doresult(WvString("%s\r", initstr()), stage==ATZ ? 3000 : 500)
	    || ((stage <= ATZ || stage == Reinit) && status[stage]==Fail) )
	{
	    tries++;

	    if (tries >= 3)
	    {
		debug("nothing.\n");
		broken = true;
	    }

	    // else try again shortly
	}
	else
	{
	    tries = 0;
	    stage++;
	}
	break;

    case GetIdent:
	assert(modem);
	status[stage] = Test;
	debug("Modem Identifier: ");
	if ( !doresult(WvString("ATI\r"), 500) || (status[stage]==Fail) )
	{
	    tries++;

	    if (tries >= 3)
	    	debug("nothing.\n");

	    // else try again shortly
	}
	else
	{
	    if (is_isdn())
	    	debug("Looks like an ISDN modem.\n");
	    tries = 0;
	    stage++;
	}

    case BaudStep:
	assert(modem);
	modem->drain();
	modem->speed(baud*2);

	// if we try 2*baud three times without success, or setting 2*baud
	// results in a lower setting than 1*baud, we have reached the
	// top speed of the modem or the serial port, respectively.
	if (tries >= 3 || modem->speed() < baud)
	{
	    // using the absolute maximum baud rate confuses many slower modems
	    // in obscure ways; step down one.
	    baud = modem->speed(baud);
	    debug("Max speed is %s; ", baud);
	    if (is_isdn())
	    {
	    	//if (modem->speed() != 230400)		// FIXME
	    	    modem->speed(115200);
	    	baud = modem->speed();
	    	debug ("using %s for ISDN modem.\n", baud);
	    }
	    else
	    {
		if (modem->speed() < 115200)
		{
		    // baud - 1 will resolve to next lower rate
		    baud = modem->speed(baud - 1);
		    debug("using %s to be safe.\n", baud);
		}
		else
		{
		    debug("assuming %s is safe.\n", baud);
		}
	    }

	    stage++;
	    status[stage] = Worked;
	    break;
	}

	debug("Speed %s: ", modem->speed());

	if (!doresult("AT\r", 500) || status[stage] == Fail)
	{
	    tries++;
	}
	else // got a response
	{
	    baud *= 2;
	    tries = 0;
	    // next time through we try a faster speed
	}
	break;

    case Done:
    case NUM_STAGES:
	assert(0);
	break; // should never happen
    }

    if (stage == Done) // we just incremented stage number to Done
    {
	if (modem)
	    delete modem;
	modem = NULL;
    }
}

bool WvModemScan::doresult(const WvString &_s, int msec)
{
    char buf[1024], *cptr;
    size_t len;
    WvString s(_s);

    modem->drain();
    usleep(50 * 1000); // delay a bit after emptying the buffer
    modem->write(s);

    debug("%s -- ", trim_string(s.edit()));

    len = coagulate(buf, sizeof(buf), msec);

    if (!len)
    {
	// debug("(no answer yet)\n");
	return false;
    }

    buf[len] = 0;

    cptr = trim_string(buf);
    while (strchr(cptr, '\r'))
    {
	cptr = trim_string(strchr(cptr, '\r'));
	if (stage == GetIdent && status[stage] == Test)
	{
	    char *p = strpbrk(cptr, "\n\r");
	    if (p) *p=0;
	    identifier = cptr;
	    status[stage] = Worked;
	    debug("%s\n", identifier);
	    return true;
	}
    }
    while (strchr(cptr, '\n'))
	cptr = trim_string(strchr(cptr, '\n'));

    debug("%s\n", cptr);

    if (!strncmp(cptr, "OK", 2))
	status[stage] = Worked;
    else
	status[stage] = Fail;

    return true;
}

size_t WvModemScan::coagulate(char *buf, size_t size, int msec)
{
    size_t len = 0, amt;
    char *cptr = buf;

    assert(modem);

    if (!modem->isok())
    {
	broken = true;
	return 0;
    }

    while (modem->select(msec))
    {
	amt = modem->read(cptr, size-1);
	cptr[amt] = 0;

	len += amt;
	size -= amt;
	cptr += amt;

	if (strstr(buf, "OK") || strstr(buf, "ERROR"))
	    break;
    }

    return len;
}

const char *WvModemScan::is_isdn() const
{
    if (!identifier)
    	return NULL;

    if (identifier == "3C882")		// 3Com Impact IQ
    	return identifier;
    if (identifier == "960")		// Motorola BitSurfr
    	return identifier;

    return NULL;
}

static int fileselect(const struct dirent *e)
{
    return !strncmp(e->d_name, "ttyS", 4);     // serial
       // (no internal ISDN support)   || !strncmp(e->d_name, "ttyI", 4);
}

static int filesort(const void *_e1, const void *_e2)
{
    dirent const * const *e1 = (dirent const * const *)_e1;
    dirent const * const *e2 = (dirent const * const *)_e2;
    const char *p1, *p2;
    int diff;

    for (p1=(*e1)->d_name, p2=(*e2)->d_name; *p1 || *p2; p1++, p2++)
    {
	if (!isdigit(*p1) || !isdigit(*p2))
	{
	    diff = *p1 - *p2;
	    if (diff) return diff;
	}
	else // both are digits
	{
	    return atoi(p1) - atoi(p2);
	}
    }

    return 0;
}

void WvModemScanList::setup()
{
    struct dirent **namelist;
    struct stat mouse, modem;
    int num, count, mousestat, modemstat;

    log = new WvLog("Port Scan", WvLog::Debug);
    thisline = -1;
    printed = false;

    mousestat = stat("/dev/mouse", &mouse);
    modemstat = stat("/dev/modem", &modem);
    num = scandir("/dev", &namelist, fileselect, filesort);

    if (num < 0)
	return;

    for (count = 0; count < num; count++)
    {
	// never search the device assigned to /dev/mouse; most mouse-using
	// programs neglect to lock the device, so we could mess up the
	// mouse response!  (We are careful to put things back when done,
	// but X seems to still get confused.)  Anyway the mouse is seldom
	// a modem.
	if (mousestat==0 && mouse.st_ino == (ino_t)namelist[count]->d_ino)
	{
	    log->print("\nIgnoring %s because /dev/mouse is a link to it.\n",
		       namelist[count]->d_name);
	    continue;
	}

	// bump /dev/modem to the top of the list, if it exists
	if (modemstat==0 && modem.st_ino == (ino_t)namelist[count]->d_ino)
	    append(new WvModemScan(WvString("%s", namelist[count]->d_name)),
		   true);
	else
	    append(new WvModemScan(WvString("%s", namelist[count]->d_name)),
		   true);
    }

    while (--num >= 0)
	free(namelist[num]);
    free(namelist);
}

void WvModemScanList::shutdown()
{
    delete log;
}

// we used to try to scan all ports simultaneously; unfortunately, this
// caused problems when people had "noncritical" IRQ conflicts (ie. two
// serial ports with the same IRQ, but they work as long as only one port
// is used at a time).  Also, the log messages looked really confused.
//
// So now we do the scanning sequentially, which is slower.  The port
// being scanned is at the head of the list.  If the probe fails, we
// unlink the element.  If it succeeds, we have found a modem -- so,
// isdone() knows we are done when the _first_ element is done.
//
void WvModemScanList::execute()
{
    assert (!isdone());

    WvModemScanList::Iter i(*this);

    for (i.rewind(); i.next(); )
	if (!i().isdone()) break;

    if (!i.cur()) return;

    WvModemScan &s(i);

    if (!s.isok())
    {
	if (!printed)
	{
	    const WvString &f = s.filename();
	    const char *cptr = strrchr(f, '/');
	    if (cptr)
		cptr++;
	    else
		cptr = f;

	    if (!strncmp(cptr, "tty", 3))
		cptr += 3;

	    ++thisline %= 8;
	    if (!thisline)
		log->print("\n");

	    log->print("%-4s ", cptr);
	}

	i.unlink();
	printed = false;
    }
    else
    {
	s.execute();

	if (s.isok())
	    printed = true;
    }

    if (isdone())
	log->write("\n", 1);
}

bool WvModemScanList::isdone()
{
    WvModemScanList::Iter i(*this);

    for (i.rewind(); i.next(); )
	if (!i().isdone()) return false;

    return true;
}
<|endoftext|>


<commit_before>/*=============================================================================

  Library: CTK

  Copyright (c) German Cancer Research Center,
    Division of Medical and Biological Informatics

  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.

=============================================================================*/

#include "ctkServiceReference.h"
#include "ctkServiceReferencePrivate.h"
#include "ctkServiceRegistrationPrivate.h"
#include "ctkPluginPrivate_p.h"
#include "ctkPluginConstants.h"

#include <QStringList>
#include <QMutexLocker>
#include <QDebug>

//----------------------------------------------------------------------------
ctkServiceReference::ctkServiceReference()
  : d_ptr(new ctkServiceReferencePrivate(0))
{

}

//----------------------------------------------------------------------------
ctkServiceReference::ctkServiceReference(const ctkServiceReference& ref)
  : d_ptr(ref.d_ptr)
{
  d_func()->ref.ref();
}

//----------------------------------------------------------------------------
ctkServiceReference::ctkServiceReference(ctkServiceRegistrationPrivate* reg)
  : d_ptr(new ctkServiceReferencePrivate(reg))
{

}

//----------------------------------------------------------------------------
ctkServiceReference::operator bool() const
{
  return getPlugin();
}

//----------------------------------------------------------------------------
ctkServiceReference& ctkServiceReference::operator=(int null)
{
  if (null == 0)
  {
    if (d_func() && !d_func()->ref.deref())
      delete d_ptr;
    d_ptr = new ctkServiceReferencePrivate(0);
  }
  return *this;
}

//----------------------------------------------------------------------------
ctkServiceReference::~ctkServiceReference()
{
  if (!d_func()->ref.deref())
    delete d_ptr;
}

//----------------------------------------------------------------------------
QVariant ctkServiceReference::getProperty(const QString& key) const
{
  Q_D(const ctkServiceReference);

  QMutexLocker lock(&d->registration->propsLock);

  return d->registration->properties.value(key);
}

//----------------------------------------------------------------------------
QStringList ctkServiceReference::getPropertyKeys() const
{
  Q_D(const ctkServiceReference);

  QMutexLocker lock(&d->registration->propsLock);

  QStringList result;
  foreach (ctkCaseInsensitiveString key, d->registration->properties.keys())
  {
    result << key;
  }
  return result;
}

//----------------------------------------------------------------------------
QSharedPointer<ctkPlugin> ctkServiceReference::getPlugin() const
{
  if (d_func()->registration == 0 || d_func()->registration->plugin == 0)
  {
    return QSharedPointer<ctkPlugin>();
  }

  return d_func()->registration->plugin->q_func().toStrongRef();
}

//----------------------------------------------------------------------------
QList<QSharedPointer<ctkPlugin> > ctkServiceReference::getUsingPlugins() const
{
  Q_D(const ctkServiceReference);

  QMutexLocker lock(&d->registration->propsLock);

  return d->registration->dependents.keys();
}

//----------------------------------------------------------------------------
bool ctkServiceReference::operator<(const ctkServiceReference& reference) const
{
  bool sameFw = d_func()->registration->plugin->fwCtx == reference.d_func()->registration->plugin->fwCtx;
  if (!sameFw)
  {
    throw std::invalid_argument("Can not compare service references "
                                "belonging to different framework "
                                "instances.");
  }

  int r1 = getProperty(ctkPluginConstants::SERVICE_RANKING).toInt();
  int r2 = reference.getProperty(ctkPluginConstants::SERVICE_RANKING).toInt();

  if (r1 != r2)
  {
    // use ranking if ranking differs
    return r1 < r2;
  }
  else
  {
    qlonglong id1 = getProperty(ctkPluginConstants::SERVICE_ID).toLongLong();
    qlonglong id2 = reference.getProperty(ctkPluginConstants::SERVICE_ID).toLongLong();

    // otherwise compare using IDs,
    // is less than if it has a higher ID.
    return id2< id1;
  }
}

//----------------------------------------------------------------------------
bool ctkServiceReference::operator==(const ctkServiceReference& reference) const
{
  return d_func()->registration == reference.d_func()->registration;
}

//----------------------------------------------------------------------------
ctkServiceReference& ctkServiceReference::operator=(const ctkServiceReference& reference)
{
  ctkServiceReferencePrivate* curr_d = d_func();
  d_ptr = reference.d_ptr;
  d_ptr->ref.ref();

  if (!curr_d->ref.deref())
    delete curr_d;

  return *this;
}

//----------------------------------------------------------------------------
uint qHash(const ctkServiceReference& serviceRef)
{
  return qHash(serviceRef.d_func()->registration);
}

//----------------------------------------------------------------------------
QDebug operator<<(QDebug dbg, const ctkServiceReference& serviceRef)
{
  dbg.nospace() << "Reference for service object registered from "
      << serviceRef.getPlugin()->getSymbolicName() << " " << serviceRef.getPlugin()->getVersion()
      << " (";
  int i = serviceRef.getPropertyKeys().size();
  foreach(QString key, serviceRef.getPropertyKeys())
  {
    dbg.nospace() << key << "=" << serviceRef.getProperty(key).toString();
    if (--i > 0) dbg.nospace() << ",";
  }
  dbg.nospace() << ")";

  return dbg.maybeSpace();
}
<commit_msg>Removed unnecessary null check.<commit_after>/*=============================================================================

  Library: CTK

  Copyright (c) German Cancer Research Center,
    Division of Medical and Biological Informatics

  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.

=============================================================================*/

#include "ctkServiceReference.h"
#include "ctkServiceReferencePrivate.h"
#include "ctkServiceRegistrationPrivate.h"
#include "ctkPluginPrivate_p.h"
#include "ctkPluginConstants.h"

#include <QStringList>
#include <QMutexLocker>
#include <QDebug>

//----------------------------------------------------------------------------
ctkServiceReference::ctkServiceReference()
  : d_ptr(new ctkServiceReferencePrivate(0))
{

}

//----------------------------------------------------------------------------
ctkServiceReference::ctkServiceReference(const ctkServiceReference& ref)
  : d_ptr(ref.d_ptr)
{
  d_func()->ref.ref();
}

//----------------------------------------------------------------------------
ctkServiceReference::ctkServiceReference(ctkServiceRegistrationPrivate* reg)
  : d_ptr(new ctkServiceReferencePrivate(reg))
{

}

//----------------------------------------------------------------------------
ctkServiceReference::operator bool() const
{
  return getPlugin();
}

//----------------------------------------------------------------------------
ctkServiceReference& ctkServiceReference::operator=(int null)
{
  if (null == 0)
  {
    if (!d_func()->ref.deref())
      delete d_ptr;
    d_ptr = new ctkServiceReferencePrivate(0);
  }
  return *this;
}

//----------------------------------------------------------------------------
ctkServiceReference::~ctkServiceReference()
{
  if (!d_func()->ref.deref())
    delete d_ptr;
}

//----------------------------------------------------------------------------
QVariant ctkServiceReference::getProperty(const QString& key) const
{
  Q_D(const ctkServiceReference);

  QMutexLocker lock(&d->registration->propsLock);

  return d->registration->properties.value(key);
}

//----------------------------------------------------------------------------
QStringList ctkServiceReference::getPropertyKeys() const
{
  Q_D(const ctkServiceReference);

  QMutexLocker lock(&d->registration->propsLock);

  QStringList result;
  foreach (ctkCaseInsensitiveString key, d->registration->properties.keys())
  {
    result << key;
  }
  return result;
}

//----------------------------------------------------------------------------
QSharedPointer<ctkPlugin> ctkServiceReference::getPlugin() const
{
  if (d_func()->registration == 0 || d_func()->registration->plugin == 0)
  {
    return QSharedPointer<ctkPlugin>();
  }

  return d_func()->registration->plugin->q_func().toStrongRef();
}

//----------------------------------------------------------------------------
QList<QSharedPointer<ctkPlugin> > ctkServiceReference::getUsingPlugins() const
{
  Q_D(const ctkServiceReference);

  QMutexLocker lock(&d->registration->propsLock);

  return d->registration->dependents.keys();
}

//----------------------------------------------------------------------------
bool ctkServiceReference::operator<(const ctkServiceReference& reference) const
{
  bool sameFw = d_func()->registration->plugin->fwCtx == reference.d_func()->registration->plugin->fwCtx;
  if (!sameFw)
  {
    throw std::invalid_argument("Can not compare service references "
                                "belonging to different framework "
                                "instances.");
  }

  int r1 = getProperty(ctkPluginConstants::SERVICE_RANKING).toInt();
  int r2 = reference.getProperty(ctkPluginConstants::SERVICE_RANKING).toInt();

  if (r1 != r2)
  {
    // use ranking if ranking differs
    return r1 < r2;
  }
  else
  {
    qlonglong id1 = getProperty(ctkPluginConstants::SERVICE_ID).toLongLong();
    qlonglong id2 = reference.getProperty(ctkPluginConstants::SERVICE_ID).toLongLong();

    // otherwise compare using IDs,
    // is less than if it has a higher ID.
    return id2< id1;
  }
}

//----------------------------------------------------------------------------
bool ctkServiceReference::operator==(const ctkServiceReference& reference) const
{
  return d_func()->registration == reference.d_func()->registration;
}

//----------------------------------------------------------------------------
ctkServiceReference& ctkServiceReference::operator=(const ctkServiceReference& reference)
{
  ctkServiceReferencePrivate* curr_d = d_func();
  d_ptr = reference.d_ptr;
  d_ptr->ref.ref();

  if (!curr_d->ref.deref())
    delete curr_d;

  return *this;
}

//----------------------------------------------------------------------------
uint qHash(const ctkServiceReference& serviceRef)
{
  return qHash(serviceRef.d_func()->registration);
}

//----------------------------------------------------------------------------
QDebug operator<<(QDebug dbg, const ctkServiceReference& serviceRef)
{
  dbg.nospace() << "Reference for service object registered from "
      << serviceRef.getPlugin()->getSymbolicName() << " " << serviceRef.getPlugin()->getVersion()
      << " (";
  int i = serviceRef.getPropertyKeys().size();
  foreach(QString key, serviceRef.getPropertyKeys())
  {
    dbg.nospace() << key << "=" << serviceRef.getProperty(key).toString();
    if (--i > 0) dbg.nospace() << ",";
  }
  dbg.nospace() << ")";

  return dbg.maybeSpace();
}
<|endoftext|>