<commit_before>//////////////////////////////////////////////////////////////////////////
//
//  Copyright (c) 2007-2010, Image Engine Design Inc. All rights reserved.
//
//  Redistribution and use in source and binary forms, with or without
//  modification, are permitted provided that the following conditions are
//  met:
//
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//
//     * Neither the name of Image Engine Design nor the names of any
//       other contributors to this software may be used to endorse or
//       promote products derived from this software without specific prior
//       written permission.
//
//  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
//  IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
//  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
//  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
//  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
//  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
//  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
//  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
//  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
//  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
//  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//////////////////////////////////////////////////////////////////////////

#include "boost/python.hpp"

#include "IECore/Op.h"
#include "IECore/Parameter.h"
#include "IECore/CompoundParameter.h"
#include "IECore/Object.h"
#include "IECore/CompoundObject.h"
#include "IECore/bindings/RunTimeTypedBinding.h"
#include "IECore/bindings/Wrapper.h"

using namespace boost;
using namespace boost::python;

namespace IECore {

class OpWrap : public Op, public Wrapper<Op>
{
	public :

		OpWrap( PyObject *self, const std::string &description, ParameterPtr resultParameter ) : Op( description, resultParameter ), Wrapper<Op>( self, this ) {};

		OpWrap( PyObject *self, const std::string &description, CompoundParameterPtr compoundParameter, ParameterPtr resultParameter ) : Op( description, compoundParameter, resultParameter ), Wrapper<Op>( self, this ) {};

		virtual ObjectPtr doOperation( ConstCompoundObjectPtr operands )
		{
			override o = this->get_override( "doOperation" );
			if( o )
			{
				ObjectPtr r = o( const_pointer_cast<CompoundObject>( operands ) );
				if( !r )
				{
					throw Exception( "doOperation() python method didn't return an Object." );
				}
				return r;
			}
			else
			{
				throw Exception( "doOperation() python method not defined" );
			}
		};

};
IE_CORE_DECLAREPTR( OpWrap );

static ParameterPtr resultParameter( const Op &o )
{
	return const_pointer_cast<Parameter>( o.resultParameter() );
}

void bindOp()
{
	using boost::python::arg;

	RunTimeTypedClass<Op, OpWrapPtr>()
		.def( init< const std::string &, ParameterPtr >( ( arg( "name" ), arg( "description" ), arg( "resultParameter") ) ) )
		.def( init< const std::string &, CompoundParameterPtr, ParameterPtr >( ( arg( "name" ), arg( "description" ), arg( "compoundParameter" ), arg( "resultParameter") ) ) )
		.def( "resultParameter", &resultParameter )
		.def( "operate", &Op::operate )
		.def( "__call__", &Op::operate )
	;

}

} // namespace IECore
<commit_msg>Fixing argument description for OpBinding.<commit_after>//////////////////////////////////////////////////////////////////////////
//
//  Copyright (c) 2007-2010, Image Engine Design Inc. All rights reserved.
//
//  Redistribution and use in source and binary forms, with or without
//  modification, are permitted provided that the following conditions are
//  met:
//
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//
//     * Neither the name of Image Engine Design nor the names of any
//       other contributors to this software may be used to endorse or
//       promote products derived from this software without specific prior
//       written permission.
//
//  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
//  IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
//  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
//  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
//  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
//  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
//  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
//  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
//  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
//  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
//  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//////////////////////////////////////////////////////////////////////////

#include "boost/python.hpp"

#include "IECore/Op.h"
#include "IECore/Parameter.h"
#include "IECore/CompoundParameter.h"
#include "IECore/Object.h"
#include "IECore/CompoundObject.h"
#include "IECore/bindings/RunTimeTypedBinding.h"
#include "IECore/bindings/Wrapper.h"

using namespace boost;
using namespace boost::python;

namespace IECore {

class OpWrap : public Op, public Wrapper<Op>
{
	public :

		OpWrap( PyObject *self, const std::string &description, ParameterPtr resultParameter ) : Op( description, resultParameter ), Wrapper<Op>( self, this ) {};

		OpWrap( PyObject *self, const std::string &description, CompoundParameterPtr compoundParameter, ParameterPtr resultParameter ) : Op( description, compoundParameter, resultParameter ), Wrapper<Op>( self, this ) {};

		virtual ObjectPtr doOperation( ConstCompoundObjectPtr operands )
		{
			override o = this->get_override( "doOperation" );
			if( o )
			{
				ObjectPtr r = o( const_pointer_cast<CompoundObject>( operands ) );
				if( !r )
				{
					throw Exception( "doOperation() python method didn't return an Object." );
				}
				return r;
			}
			else
			{
				throw Exception( "doOperation() python method not defined" );
			}
		};

};
IE_CORE_DECLAREPTR( OpWrap );

static ParameterPtr resultParameter( const Op &o )
{
	return const_pointer_cast<Parameter>( o.resultParameter() );
}

void bindOp()
{
	using boost::python::arg;

	RunTimeTypedClass<Op, OpWrapPtr>()
		.def( init< const std::string &, ParameterPtr >( ( arg( "description" ), arg( "resultParameter") ) ) )
		.def( init< const std::string &, CompoundParameterPtr, ParameterPtr >( ( arg( "description" ), arg( "compoundParameter" ), arg( "resultParameter") ) ) )
		.def( "resultParameter", &resultParameter )
		.def( "operate", &Op::operate )
		.def( "__call__", &Op::operate )
	;

}

} // namespace IECore
<|endoftext|>


<commit_before>// @(#)root/quadp:$Id$
// Author: Eddy Offermann   May 2004

/*************************************************************************
 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

/*************************************************************************
 * Parts of this file are copied from the OOQP distribution and          *
 * are subject to the following license:                                 *
 *                                                                       *
 * COPYRIGHT 2001 UNIVERSITY OF CHICAGO                                  *
 *                                                                       *
 * The copyright holder hereby grants you royalty-free rights to use,    *
 * reproduce, prepare derivative works, and to redistribute this software*
 * to others, provided that any changes are clearly documented. This     *
 * software was authored by:                                             *
 *                                                                       *
 *   E. MICHAEL GERTZ      gertz@mcs.anl.gov                             *
 *   Mathematics and Computer Science Division                           *
 *   Argonne National Laboratory                                         *
 *   9700 S. Cass Avenue                                                 *
 *   Argonne, IL 60439-4844                                              *
 *                                                                       *
 *   STEPHEN J. WRIGHT     swright@cs.wisc.edu                           *
 *   Computer Sciences Department                                        *
 *   University of Wisconsin                                             *
 *   1210 West Dayton Street                                             *
 *   Madison, WI 53706   FAX: (608)262-9777                              *
 *                                                                       *
 * Any questions or comments may be directed to one of the authors.      *
 *                                                                       *
 * ARGONNE NATIONAL LABORATORY (ANL), WITH FACILITIES IN THE STATES OF   *
 * ILLINOIS AND IDAHO, IS OWNED BY THE UNITED STATES GOVERNMENT, AND     *
 * OPERATED BY THE UNIVERSITY OF CHICAGO UNDER PROVISION OF A CONTRACT   *
 * WITH THE DEPARTMENT OF ENERGY.                                        *
 *************************************************************************/

#include "Riostream.h"
#include "TQpDataSparse.h"

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TQpDataSparse                                                        //
//                                                                      //
// Data for the sparse QP formulation                                   //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

ClassImp(TQpDataSparse)

//______________________________________________________________________________
TQpDataSparse::TQpDataSparse(Int_t nx,Int_t my,Int_t mz)
: TQpDataBase(nx,my,mz)
{
// Constructor

   fQ.ResizeTo(fNx,fNx);
   fA.ResizeTo(fMy,fNx);
   fC.ResizeTo(fMz,fNx);
}

//______________________________________________________________________________
TQpDataSparse::TQpDataSparse(TVectorD       &c_in,   TMatrixDSparse &Q_in,
                             TVectorD       &xlow_in,TVectorD       &ixlow_in,
                             TVectorD       &xupp_in,TVectorD       &ixupp_in,
                             TMatrixDSparse &A_in,   TVectorD       &bA_in,
                             TMatrixDSparse &C_in,
                             TVectorD       &clow_in,TVectorD       &iclow_in,
                             TVectorD       &cupp_in,TVectorD       &icupp_in)
{
// Constructor

   fG       .ResizeTo(c_in)    ; fG        = c_in;
   fBa      .ResizeTo(bA_in)   ; fBa       = bA_in;
   fXloBound.ResizeTo(xlow_in) ; fXloBound = xlow_in;
   fXloIndex.ResizeTo(ixlow_in); fXloIndex = ixlow_in;
   fXupBound.ResizeTo(xupp_in) ; fXupBound = xupp_in;
   fXupIndex.ResizeTo(ixupp_in); fXupIndex = ixupp_in;
   fCloBound.ResizeTo(clow_in) ; fCloBound = clow_in;
   fCloIndex.ResizeTo(iclow_in); fCloIndex = iclow_in;
   fCupBound.ResizeTo(cupp_in) ; fCupBound = cupp_in;
   fCupIndex.ResizeTo(icupp_in); fCupIndex = icupp_in;

   fNx = fG.GetNrows();
   fQ.Use(Q_in);

   if (A_in.GetNrows() > 0) {
      fA.Use(A_in);
      fMy = fA.GetNrows();
   } else
   fMy = 0;

   if (C_in.GetNrows()) {
      fC.Use(C_in);
      fMz = fC.GetNrows();
   } else
   fMz = 0;
   fQ.Print();
   fA.Print();
   fC.Print();
   printf("fNx: %d\n",fNx);
   printf("fMy: %d\n",fMy);
   printf("fMz: %d\n",fMz);
}

//______________________________________________________________________________
TQpDataSparse::TQpDataSparse(const TQpDataSparse &another) : TQpDataBase(another)
{
// Copy constructor

   *this = another;
}

//______________________________________________________________________________
void TQpDataSparse::SetNonZeros(Int_t nnzQ,Int_t nnzA,Int_t nnzC)
{
// Allocate space for the appropriate number of non-zeros in the matrices

   fQ.SetSparseIndex(nnzQ);
   fA.SetSparseIndex(nnzA);
   fC.SetSparseIndex(nnzC);
}

//______________________________________________________________________________
void TQpDataSparse::Qmult(Double_t beta,TVectorD &y,Double_t alpha,const TVectorD &x )
{
// calculate y = beta*y + alpha*(fQ*x)

   y *= beta;
   if (fQ.GetNoElements() > 0)
      y += alpha*(fQ*x);
}

//______________________________________________________________________________
void TQpDataSparse::Amult(Double_t beta,TVectorD &y,Double_t alpha,const TVectorD &x)
{
// calculate y = beta*y + alpha*(fA*x)

   y *= beta;
   if (fA.GetNoElements() > 0)
      y += alpha*(fA*x);
}

//______________________________________________________________________________
void TQpDataSparse::Cmult(Double_t beta,TVectorD &y,Double_t alpha,const TVectorD &x)
{
// calculate y = beta*y + alpha*(fC*x)

   y *= beta;
   if (fC.GetNoElements() > 0)
      y += alpha*(fC*x);
}

//______________________________________________________________________________
void TQpDataSparse::ATransmult(Double_t beta,TVectorD &y,Double_t alpha,const TVectorD &x)
{
// calculate y = beta*y + alpha*(fA^T*x)

   y *= beta;
   if (fA.GetNoElements() > 0)
      y += alpha*(TMatrixDSparse(TMatrixDSparse::kTransposed,fA)*x);
}

//______________________________________________________________________________
void TQpDataSparse::CTransmult(Double_t beta,TVectorD &y,Double_t alpha,const TVectorD &x)
{
// calculate y = beta*y + alpha*(fC^T*x)

   y *= beta;
   if (fC.GetNoElements() > 0)
      y += alpha*(TMatrixDSparse(TMatrixDSparse::kTransposed,fC)*x);
}

//______________________________________________________________________________
Double_t TQpDataSparse::DataNorm()
{
// Return the largest component of several vectors in the data class

   Double_t norm = 0.0;

   Double_t componentNorm = fG.NormInf();
   if (componentNorm > norm) norm = componentNorm;

   TMatrixDSparse fQ_abs(fQ);
   componentNorm = (fQ_abs.Abs()).Max();
   if (componentNorm > norm) norm = componentNorm;

   componentNorm = fBa.NormInf();
   if (componentNorm > norm) norm = componentNorm;

   TMatrixDSparse fA_abs(fQ);
   componentNorm = (fA_abs.Abs()).Max();
   if (componentNorm > norm) norm = componentNorm;

   TMatrixDSparse fC_abs(fQ);
   componentNorm = (fC_abs.Abs()).Max();
   if (componentNorm > norm) norm = componentNorm;

   R__ASSERT(fXloBound.MatchesNonZeroPattern(fXloIndex));
   componentNorm = fXloBound.NormInf();
   if (componentNorm > norm) norm = componentNorm;

   R__ASSERT(fXupBound.MatchesNonZeroPattern(fXupIndex));
   componentNorm = fXupBound.NormInf();
   if (componentNorm > norm) norm = componentNorm;

   R__ASSERT(fCloBound.MatchesNonZeroPattern(fCloIndex));
   componentNorm = fCloBound.NormInf();
   if (componentNorm > norm) norm = componentNorm;

   R__ASSERT(fCupBound.MatchesNonZeroPattern(fCupIndex));
   componentNorm = fCupBound.NormInf();
   if (componentNorm > norm) norm = componentNorm;

   return norm;
}

//______________________________________________________________________________
void TQpDataSparse::Print(Option_t * /*opt*/) const
{
// Print class members

   fQ.Print("Q");
   fG.Print("c");

   fXloBound.Print("xlow");
   fXloIndex.Print("ixlow");

   fXupBound.Print("xupp");
   fXupIndex.Print("ixupp");

   fA.Print("A");
   fBa.Print("b");
   fC.Print("C");

   fCloBound.Print("clow");
   fCloIndex.Print("iclow");

   fCupBound.Print("cupp");
   fCupIndex.Print("icupp");
}

//______________________________________________________________________________
void TQpDataSparse::PutQIntoAt(TMatrixDBase &m,Int_t row,Int_t col)
{
// Insert the Hessian Q into the matrix M at index (row,col) for the fundamental
// linear system

   m.SetSub(row,col,fQ);
}

//______________________________________________________________________________
void TQpDataSparse::PutAIntoAt(TMatrixDBase &m,Int_t row,Int_t col)
{
// Insert the constraint matrix A into the matrix M at index (row,col) for the fundamental
// linear system

   m.SetSub(row,col,fA);
}

//______________________________________________________________________________
void TQpDataSparse::PutCIntoAt(TMatrixDBase &m,Int_t row,Int_t col)
{
// Insert the constraint matrix C into the matrix M at index (row,col) for the fundamental
// linear system

   m.SetSub(row,col,fC);
}

//______________________________________________________________________________
void TQpDataSparse::GetDiagonalOfQ(TVectorD &dq)
{
// Return in vector dq the diagonal of matrix fQ

   const Int_t n = TMath::Min(fQ.GetNrows(),fQ.GetNcols());
   dq.ResizeTo(n);
   dq = TMatrixDSparseDiag(fQ);
}

//______________________________________________________________________________
Double_t TQpDataSparse::ObjectiveValue(TQpVar *vars)
{
// Return value of the objective function

   TVectorD tmp(fG);
   this->Qmult(1.0,tmp,0.5,vars->fX);

   return tmp*vars->fX;
}

//______________________________________________________________________________
void TQpDataSparse::DataRandom(TVectorD &x,TVectorD &y,TVectorD &z,TVectorD &s)
{
// Choose randomly a QP problem

   Double_t ix = 3074.20374;

   TVectorD xdual(fNx);
   this->RandomlyChooseBoundedVariables(x,xdual,fXloBound,fXloIndex,fXupBound,fXupIndex,ix,.25,.25,.25);

   TVectorD sprime(fMz);
   this->RandomlyChooseBoundedVariables(sprime,z,fCloBound,fCloIndex,fCupBound,fCupIndex,ix,.25,.25,.5);

   fQ.RandomizePD(0.0,1.0,ix);
   fA.Randomize(-10.0,10.0,ix);
   fC.Randomize(-10.0,10.0,ix);
   y .Randomize(-10.0,10.0,ix);

   // fG = - fQ x + A^T y + C^T z + xdual

   fG = xdual;
   fG -= fQ*x;

   fG += TMatrixDSparse(TMatrixDSparse::kTransposed,fA)*y;
   fG += TMatrixDSparse(TMatrixDSparse::kTransposed,fC)*z;

   fBa = fA*x;
   s   = fC*x;

   // Now compute the real q = s-sprime
   const TVectorD q = s-sprime;

   // Adjust fCloBound and fCupBound appropriately
   Add(fCloBound,1.0,q);
   Add(fCupBound,1.0,q);

   fCloBound.SelectNonZeros(fCloIndex);
   fCupBound.SelectNonZeros(fCupIndex);
}

//______________________________________________________________________________
TQpDataSparse &TQpDataSparse::operator=(const TQpDataSparse &source)
{
// Assignment operator

   if (this != &source) {
      TQpDataBase::operator=(source);
      fQ.ResizeTo(source.fQ); fQ = source.fQ;
      fA.ResizeTo(source.fA); fA = source.fA;
      fC.ResizeTo(source.fC); fC = source.fC;
   }
   return *this;
}
<commit_msg>remove a print out<commit_after>// @(#)root/quadp:$Id$
// Author: Eddy Offermann   May 2004

/*************************************************************************
 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

/*************************************************************************
 * Parts of this file are copied from the OOQP distribution and          *
 * are subject to the following license:                                 *
 *                                                                       *
 * COPYRIGHT 2001 UNIVERSITY OF CHICAGO                                  *
 *                                                                       *
 * The copyright holder hereby grants you royalty-free rights to use,    *
 * reproduce, prepare derivative works, and to redistribute this software*
 * to others, provided that any changes are clearly documented. This     *
 * software was authored by:                                             *
 *                                                                       *
 *   E. MICHAEL GERTZ      gertz@mcs.anl.gov                             *
 *   Mathematics and Computer Science Division                           *
 *   Argonne National Laboratory                                         *
 *   9700 S. Cass Avenue                                                 *
 *   Argonne, IL 60439-4844                                              *
 *                                                                       *
 *   STEPHEN J. WRIGHT     swright@cs.wisc.edu                           *
 *   Computer Sciences Department                                        *
 *   University of Wisconsin                                             *
 *   1210 West Dayton Street                                             *
 *   Madison, WI 53706   FAX: (608)262-9777                              *
 *                                                                       *
 * Any questions or comments may be directed to one of the authors.      *
 *                                                                       *
 * ARGONNE NATIONAL LABORATORY (ANL), WITH FACILITIES IN THE STATES OF   *
 * ILLINOIS AND IDAHO, IS OWNED BY THE UNITED STATES GOVERNMENT, AND     *
 * OPERATED BY THE UNIVERSITY OF CHICAGO UNDER PROVISION OF A CONTRACT   *
 * WITH THE DEPARTMENT OF ENERGY.                                        *
 *************************************************************************/

#include "Riostream.h"
#include "TQpDataSparse.h"

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TQpDataSparse                                                        //
//                                                                      //
// Data for the sparse QP formulation                                   //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

ClassImp(TQpDataSparse)

//______________________________________________________________________________
TQpDataSparse::TQpDataSparse(Int_t nx,Int_t my,Int_t mz)
: TQpDataBase(nx,my,mz)
{
// Constructor

   fQ.ResizeTo(fNx,fNx);
   fA.ResizeTo(fMy,fNx);
   fC.ResizeTo(fMz,fNx);
}

//______________________________________________________________________________
TQpDataSparse::TQpDataSparse(TVectorD       &c_in,   TMatrixDSparse &Q_in,
                             TVectorD       &xlow_in,TVectorD       &ixlow_in,
                             TVectorD       &xupp_in,TVectorD       &ixupp_in,
                             TMatrixDSparse &A_in,   TVectorD       &bA_in,
                             TMatrixDSparse &C_in,
                             TVectorD       &clow_in,TVectorD       &iclow_in,
                             TVectorD       &cupp_in,TVectorD       &icupp_in)
{
// Constructor

   fG       .ResizeTo(c_in)    ; fG        = c_in;
   fBa      .ResizeTo(bA_in)   ; fBa       = bA_in;
   fXloBound.ResizeTo(xlow_in) ; fXloBound = xlow_in;
   fXloIndex.ResizeTo(ixlow_in); fXloIndex = ixlow_in;
   fXupBound.ResizeTo(xupp_in) ; fXupBound = xupp_in;
   fXupIndex.ResizeTo(ixupp_in); fXupIndex = ixupp_in;
   fCloBound.ResizeTo(clow_in) ; fCloBound = clow_in;
   fCloIndex.ResizeTo(iclow_in); fCloIndex = iclow_in;
   fCupBound.ResizeTo(cupp_in) ; fCupBound = cupp_in;
   fCupIndex.ResizeTo(icupp_in); fCupIndex = icupp_in;

   fNx = fG.GetNrows();
   fQ.Use(Q_in);

   if (A_in.GetNrows() > 0) {
      fA.Use(A_in);
      fMy = fA.GetNrows();
   } else
   fMy = 0;

   if (C_in.GetNrows()) {
      fC.Use(C_in);
      fMz = fC.GetNrows();
   } else
   fMz = 0;
   // fQ.Print();
   // fA.Print();
   // fC.Print();
   // printf("fNx: %d\n",fNx);
   // printf("fMy: %d\n",fMy);
   // printf("fMz: %d\n",fMz);
}

//______________________________________________________________________________
TQpDataSparse::TQpDataSparse(const TQpDataSparse &another) : TQpDataBase(another)
{
// Copy constructor

   *this = another;
}

//______________________________________________________________________________
void TQpDataSparse::SetNonZeros(Int_t nnzQ,Int_t nnzA,Int_t nnzC)
{
// Allocate space for the appropriate number of non-zeros in the matrices

   fQ.SetSparseIndex(nnzQ);
   fA.SetSparseIndex(nnzA);
   fC.SetSparseIndex(nnzC);
}

//______________________________________________________________________________
void TQpDataSparse::Qmult(Double_t beta,TVectorD &y,Double_t alpha,const TVectorD &x )
{
// calculate y = beta*y + alpha*(fQ*x)

   y *= beta;
   if (fQ.GetNoElements() > 0)
      y += alpha*(fQ*x);
}

//______________________________________________________________________________
void TQpDataSparse::Amult(Double_t beta,TVectorD &y,Double_t alpha,const TVectorD &x)
{
// calculate y = beta*y + alpha*(fA*x)

   y *= beta;
   if (fA.GetNoElements() > 0)
      y += alpha*(fA*x);
}

//______________________________________________________________________________
void TQpDataSparse::Cmult(Double_t beta,TVectorD &y,Double_t alpha,const TVectorD &x)
{
// calculate y = beta*y + alpha*(fC*x)

   y *= beta;
   if (fC.GetNoElements() > 0)
      y += alpha*(fC*x);
}

//______________________________________________________________________________
void TQpDataSparse::ATransmult(Double_t beta,TVectorD &y,Double_t alpha,const TVectorD &x)
{
// calculate y = beta*y + alpha*(fA^T*x)

   y *= beta;
   if (fA.GetNoElements() > 0)
      y += alpha*(TMatrixDSparse(TMatrixDSparse::kTransposed,fA)*x);
}

//______________________________________________________________________________
void TQpDataSparse::CTransmult(Double_t beta,TVectorD &y,Double_t alpha,const TVectorD &x)
{
// calculate y = beta*y + alpha*(fC^T*x)

   y *= beta;
   if (fC.GetNoElements() > 0)
      y += alpha*(TMatrixDSparse(TMatrixDSparse::kTransposed,fC)*x);
}

//______________________________________________________________________________
Double_t TQpDataSparse::DataNorm()
{
// Return the largest component of several vectors in the data class

   Double_t norm = 0.0;

   Double_t componentNorm = fG.NormInf();
   if (componentNorm > norm) norm = componentNorm;

   TMatrixDSparse fQ_abs(fQ);
   componentNorm = (fQ_abs.Abs()).Max();
   if (componentNorm > norm) norm = componentNorm;

   componentNorm = fBa.NormInf();
   if (componentNorm > norm) norm = componentNorm;

   TMatrixDSparse fA_abs(fQ);
   componentNorm = (fA_abs.Abs()).Max();
   if (componentNorm > norm) norm = componentNorm;

   TMatrixDSparse fC_abs(fQ);
   componentNorm = (fC_abs.Abs()).Max();
   if (componentNorm > norm) norm = componentNorm;

   R__ASSERT(fXloBound.MatchesNonZeroPattern(fXloIndex));
   componentNorm = fXloBound.NormInf();
   if (componentNorm > norm) norm = componentNorm;

   R__ASSERT(fXupBound.MatchesNonZeroPattern(fXupIndex));
   componentNorm = fXupBound.NormInf();
   if (componentNorm > norm) norm = componentNorm;

   R__ASSERT(fCloBound.MatchesNonZeroPattern(fCloIndex));
   componentNorm = fCloBound.NormInf();
   if (componentNorm > norm) norm = componentNorm;

   R__ASSERT(fCupBound.MatchesNonZeroPattern(fCupIndex));
   componentNorm = fCupBound.NormInf();
   if (componentNorm > norm) norm = componentNorm;

   return norm;
}

//______________________________________________________________________________
void TQpDataSparse::Print(Option_t * /*opt*/) const
{
// Print class members

   fQ.Print("Q");
   fG.Print("c");

   fXloBound.Print("xlow");
   fXloIndex.Print("ixlow");

   fXupBound.Print("xupp");
   fXupIndex.Print("ixupp");

   fA.Print("A");
   fBa.Print("b");
   fC.Print("C");

   fCloBound.Print("clow");
   fCloIndex.Print("iclow");

   fCupBound.Print("cupp");
   fCupIndex.Print("icupp");
}

//______________________________________________________________________________
void TQpDataSparse::PutQIntoAt(TMatrixDBase &m,Int_t row,Int_t col)
{
// Insert the Hessian Q into the matrix M at index (row,col) for the fundamental
// linear system

   m.SetSub(row,col,fQ);
}

//______________________________________________________________________________
void TQpDataSparse::PutAIntoAt(TMatrixDBase &m,Int_t row,Int_t col)
{
// Insert the constraint matrix A into the matrix M at index (row,col) for the fundamental
// linear system

   m.SetSub(row,col,fA);
}

//______________________________________________________________________________
void TQpDataSparse::PutCIntoAt(TMatrixDBase &m,Int_t row,Int_t col)
{
// Insert the constraint matrix C into the matrix M at index (row,col) for the fundamental
// linear system

   m.SetSub(row,col,fC);
}

//______________________________________________________________________________
void TQpDataSparse::GetDiagonalOfQ(TVectorD &dq)
{
// Return in vector dq the diagonal of matrix fQ

   const Int_t n = TMath::Min(fQ.GetNrows(),fQ.GetNcols());
   dq.ResizeTo(n);
   dq = TMatrixDSparseDiag(fQ);
}

//______________________________________________________________________________
Double_t TQpDataSparse::ObjectiveValue(TQpVar *vars)
{
// Return value of the objective function

   TVectorD tmp(fG);
   this->Qmult(1.0,tmp,0.5,vars->fX);

   return tmp*vars->fX;
}

//______________________________________________________________________________
void TQpDataSparse::DataRandom(TVectorD &x,TVectorD &y,TVectorD &z,TVectorD &s)
{
// Choose randomly a QP problem

   Double_t ix = 3074.20374;

   TVectorD xdual(fNx);
   this->RandomlyChooseBoundedVariables(x,xdual,fXloBound,fXloIndex,fXupBound,fXupIndex,ix,.25,.25,.25);

   TVectorD sprime(fMz);
   this->RandomlyChooseBoundedVariables(sprime,z,fCloBound,fCloIndex,fCupBound,fCupIndex,ix,.25,.25,.5);

   fQ.RandomizePD(0.0,1.0,ix);
   fA.Randomize(-10.0,10.0,ix);
   fC.Randomize(-10.0,10.0,ix);
   y .Randomize(-10.0,10.0,ix);

   // fG = - fQ x + A^T y + C^T z + xdual

   fG = xdual;
   fG -= fQ*x;

   fG += TMatrixDSparse(TMatrixDSparse::kTransposed,fA)*y;
   fG += TMatrixDSparse(TMatrixDSparse::kTransposed,fC)*z;

   fBa = fA*x;
   s   = fC*x;

   // Now compute the real q = s-sprime
   const TVectorD q = s-sprime;

   // Adjust fCloBound and fCupBound appropriately
   Add(fCloBound,1.0,q);
   Add(fCupBound,1.0,q);

   fCloBound.SelectNonZeros(fCloIndex);
   fCupBound.SelectNonZeros(fCupIndex);
}

//______________________________________________________________________________
TQpDataSparse &TQpDataSparse::operator=(const TQpDataSparse &source)
{
// Assignment operator

   if (this != &source) {
      TQpDataBase::operator=(source);
      fQ.ResizeTo(source.fQ); fQ = source.fQ;
      fA.ResizeTo(source.fA); fA = source.fA;
      fC.ResizeTo(source.fC); fC = source.fC;
   }
   return *this;
}
<|endoftext|>


<commit_before>#pragma once
#include <sdbusplus/bus.hpp>

namespace sdbusplus
{

namespace server
{

namespace object
{

namespace details
{

/** Templates to allow multiple inheritence via template parameters.
 *
 *  These allow an object to group multiple dbus interface bindings into a
 *  single class.
 */
template <class T, class... Rest> struct compose_impl :
        T, compose_impl<Rest...>
{
    compose_impl(bus::bus& bus, const char* path) :
        T(bus, path), compose_impl<Rest...>(bus, path) {}
};

/** Specialization for single element. */
template <class T> struct compose_impl<T> : T
{
    compose_impl(bus::bus& bus, const char* path) :
        T(bus, path) {}
};

/** Default compose operation for variadic arguments. */
template <class... Args> struct compose : compose_impl<Args...>
{
    compose(bus::bus& bus, const char* path) :
        compose_impl<Args...>(bus, path) {}
};

/** Specialization for zero variadic arguments. */
template <> struct compose<>
{
    compose(bus::bus& bus, const char* path) {}
};

} // namespace details

/** Class to compose multiple dbus interfaces and object signals.
 *
 *  Any number of classes representing a dbus interface may be composed into
 *  a single dbus object.  The interfaces will be created first and hooked
 *  into the object space via the 'add_object_vtable' calls.  Afterwards,
 *  a signal will be emitted for the whole object to indicate all new
 *  interfaces via 'sd_bus_emit_object_added'.
 *
 *  Similar, on destruction, the interfaces are removed (unref'd) and the
 *  'sd_bus_emit_object_removed' signals are emitted.
 *
 */
template<class... Args>
struct object : details::compose<Args...>
{
        /* Define all of the basic class operations:
         *     Not allowed:
         *         - Default constructor to avoid nullptrs.
         *         - Copy operations due to internal unique_ptr.
         *     Allowed:
         *         - Move operations.
         *         - Destructor.
         */
    object() = delete;
    object(const object&) = delete;
    object& operator=(const object&) = delete;
    object(object&&) = default;
    object& operator=(object&&) = default;

    /** Construct an 'object' on a bus with a path.
     *
     *  @param[in] bus - The bus to place the object on.
     *  @param[in] path - The path the object resides at.
     *  @param[in] deferSignal - Set to true if emit_object_added should be
     *                           deferred.  This would likely be true if the
     *                           object needs custom property init before the
     *                           signal can be sent.
     */
    object(bus::bus& bus,
           const char* path,
           bool deferSignal = false)
        : details::compose<Args...>(bus, path),
          __sdbusplus_server_object_bus(sd_bus_ref(bus.get())),
          __sdbusplus_server_object_path(path),
          __sdbusplus_server_object_emitremoved(false)
    {
        if (!deferSignal)
        {
            emit_object_added();
        }
    }

    ~object()
    {
        sd_bus_emit_object_removed(__sdbusplus_server_object_bus.get(),
                                   __sdbusplus_server_object_path.c_str());
    }

    /** Emit the 'object-added' signal, if not already sent. */
    void emit_object_added()
    {
        if (!__sdbusplus_server_object_emitremoved)
        {
            sd_bus_emit_object_added(__sdbusplus_server_object_bus.get(),
                                     __sdbusplus_server_object_path.c_str());
            __sdbusplus_server_object_emitremoved = true;
        }
    }

    private:
        // These member names are purposefully chosen as long and, hopefully,
        // unique.  Since an object is 'composed' via multiple-inheritence,
        // all members need to have unique names to ensure there is no
        // ambiguity.
        bus::bus __sdbusplus_server_object_bus;
        std::string __sdbusplus_server_object_path;
        bool __sdbusplus_server_object_emitremoved;

};

} // namespace object

template <class... Args> using object_t = object::object<Args...>;

} // namespace server
} // namespace sdbusplus
<commit_msg>Don't emit InterfacesRemoved unless requested<commit_after>#pragma once
#include <sdbusplus/bus.hpp>

namespace sdbusplus
{

namespace server
{

namespace object
{

namespace details
{

/** Templates to allow multiple inheritence via template parameters.
 *
 *  These allow an object to group multiple dbus interface bindings into a
 *  single class.
 */
template <class T, class... Rest> struct compose_impl :
        T, compose_impl<Rest...>
{
    compose_impl(bus::bus& bus, const char* path) :
        T(bus, path), compose_impl<Rest...>(bus, path) {}
};

/** Specialization for single element. */
template <class T> struct compose_impl<T> : T
{
    compose_impl(bus::bus& bus, const char* path) :
        T(bus, path) {}
};

/** Default compose operation for variadic arguments. */
template <class... Args> struct compose : compose_impl<Args...>
{
    compose(bus::bus& bus, const char* path) :
        compose_impl<Args...>(bus, path) {}
};

/** Specialization for zero variadic arguments. */
template <> struct compose<>
{
    compose(bus::bus& bus, const char* path) {}
};

} // namespace details

/** Class to compose multiple dbus interfaces and object signals.
 *
 *  Any number of classes representing a dbus interface may be composed into
 *  a single dbus object.  The interfaces will be created first and hooked
 *  into the object space via the 'add_object_vtable' calls.  Afterwards,
 *  a signal will be emitted for the whole object to indicate all new
 *  interfaces via 'sd_bus_emit_object_added'.
 *
 *  Similar, on destruction, the interfaces are removed (unref'd) and the
 *  'sd_bus_emit_object_removed' signals are emitted.
 *
 */
template<class... Args>
struct object : details::compose<Args...>
{
        /* Define all of the basic class operations:
         *     Not allowed:
         *         - Default constructor to avoid nullptrs.
         *         - Copy operations due to internal unique_ptr.
         *     Allowed:
         *         - Move operations.
         *         - Destructor.
         */
    object() = delete;
    object(const object&) = delete;
    object& operator=(const object&) = delete;
    object(object&&) = default;
    object& operator=(object&&) = default;

    /** Construct an 'object' on a bus with a path.
     *
     *  @param[in] bus - The bus to place the object on.
     *  @param[in] path - The path the object resides at.
     *  @param[in] deferSignal - Set to true if emit_object_added should be
     *                           deferred.  This would likely be true if the
     *                           object needs custom property init before the
     *                           signal can be sent.
     */
    object(bus::bus& bus,
           const char* path,
           bool deferSignal = false)
        : details::compose<Args...>(bus, path),
          __sdbusplus_server_object_bus(sd_bus_ref(bus.get())),
          __sdbusplus_server_object_path(path),
          __sdbusplus_server_object_emitremoved(false)
    {
        if (!deferSignal)
        {
            emit_object_added();
        }
    }

    ~object()
    {
        if (__sdbusplus_server_object_emitremoved)
        {
            sd_bus_emit_object_removed(__sdbusplus_server_object_bus.get(),
                                       __sdbusplus_server_object_path.c_str());
        }
    }

    /** Emit the 'object-added' signal, if not already sent. */
    void emit_object_added()
    {
        if (!__sdbusplus_server_object_emitremoved)
        {
            sd_bus_emit_object_added(__sdbusplus_server_object_bus.get(),
                                     __sdbusplus_server_object_path.c_str());
            __sdbusplus_server_object_emitremoved = true;
        }
    }

    private:
        // These member names are purposefully chosen as long and, hopefully,
        // unique.  Since an object is 'composed' via multiple-inheritence,
        // all members need to have unique names to ensure there is no
        // ambiguity.
        bus::bus __sdbusplus_server_object_bus;
        std::string __sdbusplus_server_object_path;
        bool __sdbusplus_server_object_emitremoved;

};

} // namespace object

template <class... Args> using object_t = object::object<Args...>;

} // namespace server
} // namespace sdbusplus
<|endoftext|>


<commit_before>/*
    This file is part of libkcal.
    Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public License
    along with this library; see the file COPYING.LIB.  If not, write to
    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    Boston, MA 02111-1307, USA.
*/

#include <kdebug.h>

#include "calfilter.h"

using namespace KCal;

CalFilter::CalFilter()
{
  mEnabled = true;
  mCriteria = 0;
}

CalFilter::CalFilter(const QString &name)
{
  mName = name;
}

CalFilter::~CalFilter()
{
}

void CalFilter::apply( Event::List *eventlist )
{
  if ( !mEnabled ) return;

//  kdDebug(5800) << "CalFilter::apply()" << endl;

  Event::List::Iterator it = eventlist->begin();
  while( it != eventlist->end() ) {
    if ( !filterEvent( *it ) ) {
      eventlist->remove( it );
    } else {
      ++it;
    }
  }

//  kdDebug(5800) << "CalFilter::apply() done" << endl;
}

// TODO: avoid duplicating apply() code
void CalFilter::apply( Todo::List *eventlist )
{
  if ( !mEnabled ) return;

//  kdDebug(5800) << "CalFilter::apply()" << endl;

  Todo::List::Iterator it = eventlist->begin();
  while( it != eventlist->end() ) {
    if ( !filterTodo( *it ) ) {
      eventlist->remove( it );
    } else {
      ++it;
    }
  }

//  kdDebug(5800) << "CalFilter::apply() done" << endl;
}

bool CalFilter::filterEvent(Event *event)
{
//  kdDebug(5800) << "CalFilter::filterEvent(): " << event->getSummary() << endl;

  if (mCriteria & HideRecurring) {
    if (event->recurrence()->doesRecur()) return false;
  }

  return filterIncidence(event);
}

bool CalFilter::filterTodo(Todo *todo)
{
//  kdDebug(5800) << "CalFilter::filterEvent(): " << event->getSummary() << endl;

  if (mCriteria & HideCompleted) {
    if (todo->isCompleted()) return false;
  }

  return filterIncidence(todo);
}

bool CalFilter::filterIncidence(Incidence *incidence)
{
//  kdDebug(5800) << "CalFilter::filterEvent(): " << event->getSummary() << endl;

  if (mCriteria & ShowCategories) {
    for (QStringList::Iterator it = mCategoryList.begin();
         it != mCategoryList.end(); ++it ) {
      QStringList incidenceCategories = incidence->categories();
      for (QStringList::Iterator it2 = incidenceCategories.begin();
           it2 != incidenceCategories.end(); ++it2 ) {
        if ((*it) == (*it2)) {
          return true;
        }
      }
    }
    return false;
  } else {
    for (QStringList::Iterator it = mCategoryList.begin();
         it != mCategoryList.end(); ++it ) {
      QStringList incidenceCategories = incidence->categories();
      for (QStringList::Iterator it2 = incidenceCategories.begin();
           it2 != incidenceCategories.end(); ++it2 ) {
        if ((*it) == (*it2)) {
          return false;
        }
      }
    }
    return true;
  }

//  kdDebug(5800) << "CalFilter::filterEvent(): passed" << endl;

  return true;
}

void CalFilter::setEnabled(bool enabled)
{
  mEnabled = enabled;
}

bool CalFilter::isEnabled()
{
  return mEnabled;
}

void CalFilter::setCriteria(int criteria)
{
  mCriteria = criteria;
}

int CalFilter::criteria()
{
  return mCriteria;
}

void CalFilter::setCategoryList(const QStringList &categoryList)
{
  mCategoryList = categoryList;
}

QStringList CalFilter::categoryList()
{
  return mCategoryList;
}
<commit_msg>Fixed crash #56348<commit_after>/*
    This file is part of libkcal.
    Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public License
    along with this library; see the file COPYING.LIB.  If not, write to
    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    Boston, MA 02111-1307, USA.
*/

#include <kdebug.h>

#include "calfilter.h"

using namespace KCal;

CalFilter::CalFilter()
{
  mEnabled = true;
  mCriteria = 0;
}

CalFilter::CalFilter(const QString &name)
{
  mName = name;
}

CalFilter::~CalFilter()
{
}

void CalFilter::apply( Event::List *eventlist )
{
  if ( !mEnabled ) return;

//  kdDebug(5800) << "CalFilter::apply()" << endl;

  Event::List::Iterator it = eventlist->begin();
  while( it != eventlist->end() ) {
    if ( !filterEvent( *it ) ) {
      eventlist->remove( it );
    } else {
      ++it;
    }
  }

//  kdDebug(5800) << "CalFilter::apply() done" << endl;
}

// TODO: avoid duplicating apply() code
void CalFilter::apply( Todo::List *eventlist )
{
  if ( !mEnabled ) return;

//  kdDebug(5800) << "CalFilter::apply()" << endl;

  Todo::List::Iterator it = eventlist->begin();
  while( it != eventlist->end() ) {
    if ( !filterTodo( *it ) ) {
      it = eventlist->remove( it );
    } else {
      ++it;
    }
  }

//  kdDebug(5800) << "CalFilter::apply() done" << endl;
}

bool CalFilter::filterEvent(Event *event)
{
//  kdDebug(5800) << "CalFilter::filterEvent(): " << event->getSummary() << endl;

  if (mCriteria & HideRecurring) {
    if (event->recurrence()->doesRecur()) return false;
  }

  return filterIncidence(event);
}

bool CalFilter::filterTodo(Todo *todo)
{
//  kdDebug(5800) << "CalFilter::filterEvent(): " << event->getSummary() << endl;

  if (mCriteria & HideCompleted) {
    if (todo->isCompleted()) return false;
  }

  return filterIncidence(todo);
}

bool CalFilter::filterIncidence(Incidence *incidence)
{
//  kdDebug(5800) << "CalFilter::filterEvent(): " << event->getSummary() << endl;

  if (mCriteria & ShowCategories) {
    for (QStringList::Iterator it = mCategoryList.begin();
         it != mCategoryList.end(); ++it ) {
      QStringList incidenceCategories = incidence->categories();
      for (QStringList::Iterator it2 = incidenceCategories.begin();
           it2 != incidenceCategories.end(); ++it2 ) {
        if ((*it) == (*it2)) {
          return true;
        }
      }
    }
    return false;
  } else {
    for (QStringList::Iterator it = mCategoryList.begin();
         it != mCategoryList.end(); ++it ) {
      QStringList incidenceCategories = incidence->categories();
      for (QStringList::Iterator it2 = incidenceCategories.begin();
           it2 != incidenceCategories.end(); ++it2 ) {
        if ((*it) == (*it2)) {
          return false;
        }
      }
    }
    return true;
  }

//  kdDebug(5800) << "CalFilter::filterEvent(): passed" << endl;

  return true;
}

void CalFilter::setEnabled(bool enabled)
{
  mEnabled = enabled;
}

bool CalFilter::isEnabled()
{
  return mEnabled;
}

void CalFilter::setCriteria(int criteria)
{
  mCriteria = criteria;
}

int CalFilter::criteria()
{
  return mCriteria;
}

void CalFilter::setCategoryList(const QStringList &categoryList)
{
  mCategoryList = categoryList;
}

QStringList CalFilter::categoryList()
{
  return mCategoryList;
}
<|endoftext|>


<commit_before>#include "stacktrace.h"
#include <climits>
#include <csignal>
#include <cstdio>
#include <cstdlib>
#include <cxxabi.h>
#include <stdexcept>

void debug::signal_callback_handler(int status) {
    switch(status) {
        case SIGTERM: {
            debug::print_stack_trace();
            std::fprintf(stderr, "Exit SIGTERM: %d\n", status);
            break;
        }
        case SIGSTOP: {
            std::fprintf(stderr, "Exit SIGSTOP: %d\n", status);
            break;
        }
        case SIGCHLD: {
            std::fprintf(stderr, "Exit SIGCHLD: %d\n", status);
            break;
        }
        case SIGKILL: {
            std::fprintf(stderr, "Exit SIGKILL: %d\n", status);
            break;
        }
        case SIGINT: {
            std::fprintf(stderr, "Exit SIGINT: %d\n", status);
            break;
        }
        case SIGHUP: {
            std::fprintf(stderr, "Exit SIGHUP: %d\n", status);
            break;
        }
        case SIGQUIT: {
            std::fprintf(stderr, "Exit SIGQUIT: %d\n", status);
            break;
        }
        case SIGABRT: {
            debug::print_stack_trace();
            std::fprintf(stderr, "Exit SIGABRT: %d\n", status);
            break;
        }
        case SIGILL: {
            debug::print_stack_trace();
            std::fprintf(stderr, "Exit SIGILL: %d\n", status);
            break;
        }
        case SIGFPE: {
            debug::print_stack_trace();
            std::fprintf(stderr, "Exit SIGFPE: %d\n", status);
            break;
        }
        case SIGSEGV: {
            debug::print_stack_trace();
            std::fprintf(stderr, "Exit SIGSEGV: %d\n", status);
            break;
        }
        default: {
            debug::print_stack_trace();
            std::fprintf(stderr, "Exit %d\n", status);
            break;
        }
    }

    std::exit(status);
}

void debug::register_callbacks() {
    signal(SIGTERM, signal_callback_handler);
    signal(SIGKILL, signal_callback_handler);
    signal(SIGINT, signal_callback_handler);
    signal(SIGHUP, signal_callback_handler);
    signal(SIGQUIT, signal_callback_handler);
    signal(SIGABRT, signal_callback_handler);
    signal(SIGSEGV, signal_callback_handler);

    /* ISO C99 signals.  */
    signal(SIGINT, signal_callback_handler);  //	 2	/* Interactive attention signal.  */
    signal(SIGILL, signal_callback_handler);  //	 4	/* Illegal instruction.  */
    signal(SIGABRT, signal_callback_handler); //	 6	/* Abnormal termination.  */
    signal(SIGFPE, signal_callback_handler);  //	 8	/* Erroneous arithmetic operation.  */
    signal(SIGSEGV, signal_callback_handler); //	 11	/* Invalid access to storage.  */
    signal(SIGTERM, signal_callback_handler); //	 15	/* Termination request.  */

    /* Historical signals specified by POSIX. */
    signal(SIGHUP, signal_callback_handler);  //	 1	/* Hangup.  */
    signal(SIGQUIT, signal_callback_handler); //	 3	/* Quit.  */
    signal(SIGTRAP, signal_callback_handler); //	 5	/* Trace/breakpoint trap.  */
    signal(SIGKILL, signal_callback_handler); //	 9	/* Killed. This one is special and can't be caught  */
    signal(SIGBUS, signal_callback_handler);  //	 10	/* Bus error.  */
    signal(SIGSYS, signal_callback_handler);  //	 12	/* Bad system call.  */
    signal(SIGPIPE, signal_callback_handler); //	 13	/* Broken pipe.  */
    signal(SIGALRM, signal_callback_handler); //	 14	/* Alarm clock.  */

    /* New(er) POSIX signals (1003.1-2008, 1003.1-2013).  */
    signal(SIGURG, signal_callback_handler);    //   16 /* Urgent data is available at a socket.  */
    signal(SIGSTOP, signal_callback_handler);   //   17 /* Stop, unblockable.  This one is special and can't be caught  */
    signal(SIGTSTP, signal_callback_handler);   //   18 /* Keyboard stop.  */
    signal(SIGCONT, signal_callback_handler);   //   19 /* Continue.  */
    signal(SIGCHLD, signal_callback_handler);   //   20 /* Child terminated or stopped.  */
    signal(SIGTTIN, signal_callback_handler);   //   21 /* Background read from control terminal.  */
    signal(SIGTTOU, signal_callback_handler);   //   22 /* Background write to control terminal.  */
    signal(SIGPOLL, signal_callback_handler);   //   23 /* Pollable event occurred (System V).  */
    signal(SIGXCPU, signal_callback_handler);   //   24 /* CPU time limit exceeded.  */
    signal(SIGXFSZ, signal_callback_handler);   //   25 /* File size limit exceeded.  */
    signal(SIGVTALRM, signal_callback_handler); //   26 /* Virtual timer expired.  */
    signal(SIGPROF, signal_callback_handler);   //   27 /* Profiling timer expired.  */
    signal(SIGUSR1, signal_callback_handler);   //   30 /* User-defined signal 1.  */
    signal(SIGUSR2, signal_callback_handler);   //   31 /* User-defined signal 2.  */
    signal(137, signal_callback_handler);       //   137 /* LLDB?  */
}

#if __has_include(<backward.hpp>)
    #include <backward.hpp>
void debug::print_stack_trace() {
    backward::StackTrace st;
    st.load_here(64);
    // Skip this scope (1) , as well as the signal_callback_handler scope (2)
    st.skip_n_firsts(2);
    backward::Printer p;
    p.print(st);
}

#elif __has_include(<libunwind.h>) && defined(DMRG_HAS_UNWIND)

    #define UNW_LOCAL_ONLY
    #include <array>
    #include <climits>
    #include <cstdio>
    #include <cstdlib>
    #include <execinfo.h>
    #include <libunwind.h>
    #include <memory>
    #include <unistd.h>
    #include <vector>

std::string getexepath() {
    static char result[PATH_MAX];
    ssize_t     count = readlink("/proc/self/exe", result, PATH_MAX);
    return std::string(result, (count > 0) ? static_cast<unsigned long>(count) : 0);
}

std::string sh(std::string_view cmd) {
    std::array<char, 256> buffer{};
    std::string           result;
    std::shared_ptr<FILE> pipe(popen(cmd.data(), "r"), pclose);
    if(!pipe) return std::string();
    while(!feof(pipe.get())) {
        if(fgets(buffer.data(), 256, pipe.get()) != nullptr) { result += buffer.data(); }
    }
    return result;
}

std::string getErrorLocation(unw_word_t addr) {
    // our program need to be passed after the -e parameter
    auto exec_path = getexepath();
    // Generate a hex address for addr2line
    char hex_addr[16];
    snprintf(hex_addr, 16, "0x%lx", addr);

    // Generate the command and call it
    std::string cmd       = "addr2line --exe " + exec_path + " --functions --demangle " + hex_addr;
    auto        locString = sh(cmd);
    if(locString.empty()) return locString;

    // Format the string
    size_t start_pos = 0;
    while((start_pos = locString.find('\n', start_pos)) != std::string::npos) {
        if(start_pos >= locString.size() - 1)
            locString.replace(start_pos, 1, "");
        else
            locString.replace(start_pos, 1, " in file ");
        start_pos += 1;
    }
    if(locString.find("??") != std::string::npos)
        return std::string();
    else
        return locString;
}

void debug::print_stack_trace() {
    unw_cursor_t  cursor;
    unw_context_t context;
    // Initialize cursor to current frame for local unwinding.
    unw_getcontext(&context);
    unw_init_local(&cursor, &context);
    int count = 0;
    // Unwind frames one by one, going up the frame stack.
    while(unw_step(&cursor) > 0) {
        unw_word_t offset, ip;
        unw_get_reg(&cursor, UNW_REG_IP, &ip);
        if(ip == 0) { break; }
        char sym[1024];
        if(unw_get_proc_name(&cursor, sym, sizeof(sym), &offset) == 0) {
            std::printf("#%-3d 0x%-10lx", count++, ip);
            auto estr = getErrorLocation(ip);
            if(not estr.empty())
                std::printf(" %s\n", estr.c_str());
            else {
                int   status;
                char *nameptr   = sym;
                char *demangled = abi::__cxa_demangle(sym, nullptr, nullptr, &status);
                if(status == 0) { nameptr = demangled; }
                std::printf(" %s\n", nameptr);
                std::free(demangled);
            }

        } else {
            std::printf(" -- error: unable to obtain symbol name for this frame\n");
        }
    }
}

#else
void debug::print_stack_trace() {}
#endif
<commit_msg>Print stack trace last<commit_after>#include "stacktrace.h"
#include <climits>
#include <csignal>
#include <cstdio>
#include <cstdlib>
#include <cxxabi.h>
#include <stdexcept>

void debug::signal_callback_handler(int status) {
    switch(status) {
        case SIGTERM: {
            //            debug::print_stack_trace();
            std::fprintf(stderr, "Exit SIGTERM: %d\n", status);
            break;
        }
        case SIGSTOP: {
            std::fprintf(stderr, "Exit SIGSTOP: %d\n", status);
            break;
        }
        case SIGCHLD: {
            std::fprintf(stderr, "Exit SIGCHLD: %d\n", status);
            break;
        }
        case SIGKILL: {
            std::fprintf(stderr, "Exit SIGKILL: %d\n", status);
            break;
        }
        case SIGINT: {
            std::fprintf(stderr, "Exit SIGINT: %d\n", status);
            break;
        }
        case SIGHUP: {
            std::fprintf(stderr, "Exit SIGHUP: %d\n", status);
            break;
        }
        case SIGQUIT: {
            std::fprintf(stderr, "Exit SIGQUIT: %d\n", status);
            break;
        }
        case SIGABRT: {
            //            debug::print_stack_trace();
            std::fprintf(stderr, "Exit SIGABRT: %d\n", status);
            break;
        }
        case SIGILL: {
            //            debug::print_stack_trace();
            std::fprintf(stderr, "Exit SIGILL: %d\n", status);
            break;
        }
        case SIGFPE: {
            //            debug::print_stack_trace();
            std::fprintf(stderr, "Exit SIGFPE: %d\n", status);
            break;
        }
        case SIGSEGV: {
            //            debug::print_stack_trace();
            std::fprintf(stderr, "Exit SIGSEGV: %d\n", status);
            break;
        }
        default: {
            //            debug::print_stack_trace();
            std::fprintf(stderr, "Exit %d\n", status);
            break;
        }
    }
    std::exit(status);
}

void debug::register_callbacks() {
    signal(SIGTERM, signal_callback_handler);
    signal(SIGKILL, signal_callback_handler);
    signal(SIGINT, signal_callback_handler);
    signal(SIGHUP, signal_callback_handler);
    signal(SIGQUIT, signal_callback_handler);
    signal(SIGABRT, signal_callback_handler);
    signal(SIGSEGV, signal_callback_handler);

    /* ISO C99 signals.  */
    signal(SIGINT, signal_callback_handler);  //	 2	/* Interactive attention signal.  */
    signal(SIGILL, signal_callback_handler);  //	 4	/* Illegal instruction.  */
    signal(SIGABRT, signal_callback_handler); //	 6	/* Abnormal termination.  */
    signal(SIGFPE, signal_callback_handler);  //	 8	/* Erroneous arithmetic operation.  */
    signal(SIGSEGV, signal_callback_handler); //	 11	/* Invalid access to storage.  */
    signal(SIGTERM, signal_callback_handler); //	 15	/* Termination request.  */

    /* Historical signals specified by POSIX. */
    signal(SIGHUP, signal_callback_handler);  //	 1	/* Hangup.  */
    signal(SIGQUIT, signal_callback_handler); //	 3	/* Quit.  */
    signal(SIGTRAP, signal_callback_handler); //	 5	/* Trace/breakpoint trap.  */
    signal(SIGKILL, signal_callback_handler); //	 9	/* Killed. This one is special and can't be caught  */
    signal(SIGBUS, signal_callback_handler);  //	 10	/* Bus error.  */
    signal(SIGSYS, signal_callback_handler);  //	 12	/* Bad system call.  */
    signal(SIGPIPE, signal_callback_handler); //	 13	/* Broken pipe.  */
    signal(SIGALRM, signal_callback_handler); //	 14	/* Alarm clock.  */

    /* New(er) POSIX signals (1003.1-2008, 1003.1-2013).  */
    signal(SIGURG, signal_callback_handler);    //   16 /* Urgent data is available at a socket.  */
    signal(SIGSTOP, signal_callback_handler);   //   17 /* Stop, unblockable.  This one is special and can't be caught  */
    signal(SIGTSTP, signal_callback_handler);   //   18 /* Keyboard stop.  */
    signal(SIGCONT, signal_callback_handler);   //   19 /* Continue.  */
    signal(SIGCHLD, signal_callback_handler);   //   20 /* Child terminated or stopped.  */
    signal(SIGTTIN, signal_callback_handler);   //   21 /* Background read from control terminal.  */
    signal(SIGTTOU, signal_callback_handler);   //   22 /* Background write to control terminal.  */
    signal(SIGPOLL, signal_callback_handler);   //   23 /* Pollable event occurred (System V).  */
    signal(SIGXCPU, signal_callback_handler);   //   24 /* CPU time limit exceeded.  */
    signal(SIGXFSZ, signal_callback_handler);   //   25 /* File size limit exceeded.  */
    signal(SIGVTALRM, signal_callback_handler); //   26 /* Virtual timer expired.  */
    signal(SIGPROF, signal_callback_handler);   //   27 /* Profiling timer expired.  */
    signal(SIGUSR1, signal_callback_handler);   //   30 /* User-defined signal 1.  */
    signal(SIGUSR2, signal_callback_handler);   //   31 /* User-defined signal 2.  */
    signal(137, signal_callback_handler);       //   137 /* LLDB?  */

    std::atexit(debug::print_stack_trace);
    std::at_quick_exit(debug::print_stack_trace);
}

#if __has_include(<backward.hpp>)
    #include <backward.hpp>
void debug::print_stack_trace() {
    backward::StackTrace st;
    st.load_here(64);
    // Skip this scope (1) , as well as the signal_callback_handler scope (2)
    st.skip_n_firsts(2);
    backward::Printer p;
    p.print(st);
}

#elif __has_include(<libunwind.h>) && defined(DMRG_HAS_UNWIND)

    #define UNW_LOCAL_ONLY
    #include <array>
    #include <climits>
    #include <cstdio>
    #include <cstdlib>
    #include <execinfo.h>
    #include <libunwind.h>
    #include <memory>
    #include <unistd.h>
    #include <vector>

std::string getexepath() {
    static char result[PATH_MAX];
    ssize_t     count = readlink("/proc/self/exe", result, PATH_MAX);
    return std::string(result, (count > 0) ? static_cast<unsigned long>(count) : 0);
}

std::string sh(std::string_view cmd) {
    std::array<char, 256> buffer{};
    std::string           result;
    std::shared_ptr<FILE> pipe(popen(cmd.data(), "r"), pclose);
    if(!pipe) return std::string();
    while(!feof(pipe.get())) {
        if(fgets(buffer.data(), 256, pipe.get()) != nullptr) { result += buffer.data(); }
    }
    return result;
}

std::string getErrorLocation(unw_word_t addr) {
    // our program need to be passed after the -e parameter
    auto exec_path = getexepath();
    // Generate a hex address for addr2line
    char hex_addr[16];
    snprintf(hex_addr, 16, "0x%lx", addr);

    // Generate the command and call it
    std::string cmd       = "addr2line --exe " + exec_path + " --functions --demangle " + hex_addr;
    auto        locString = sh(cmd);
    if(locString.empty()) return locString;

    // Format the string
    size_t start_pos = 0;
    while((start_pos = locString.find('\n', start_pos)) != std::string::npos) {
        if(start_pos >= locString.size() - 1)
            locString.replace(start_pos, 1, "");
        else
            locString.replace(start_pos, 1, " in file ");
        start_pos += 1;
    }
    if(locString.find("??") != std::string::npos)
        return std::string();
    else
        return locString;
}

void debug::print_stack_trace() {
    unw_cursor_t  cursor;
    unw_context_t context;
    // Initialize cursor to current frame for local unwinding.
    unw_getcontext(&context);
    unw_init_local(&cursor, &context);
    int count = 0;
    // Unwind frames one by one, going up the frame stack.
    while(unw_step(&cursor) > 0) {
        unw_word_t offset, ip;
        unw_get_reg(&cursor, UNW_REG_IP, &ip);
        if(ip == 0) { break; }
        char sym[1024];
        if(unw_get_proc_name(&cursor, sym, sizeof(sym), &offset) == 0) {
            std::printf("#%-3d 0x%-10lx", count++, ip);
            auto estr = getErrorLocation(ip);
            if(not estr.empty())
                std::printf(" %s\n", estr.c_str());
            else {
                int   status;
                char *nameptr   = sym;
                char *demangled = abi::__cxa_demangle(sym, nullptr, nullptr, &status);
                if(status == 0) { nameptr = demangled; }
                std::printf(" %s\n", nameptr);
                std::free(demangled);
            }

        } else {
            std::printf(" -- error: unable to obtain symbol name for this frame\n");
        }
    }
}

#else
void debug::print_stack_trace() {}
#endif
<|endoftext|>


<commit_before>/*
    Title:      Mutex and Condition Variable library.

    Copyright (c) 2007 David C. J. Matthews

    Portions of this code are derived from the original stream io
    package copyright CUTS 1983-2000.

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

*/

#ifdef WIN32
#include "winconfig.h"
#else
#include "config.h"
#endif

#ifdef HAVE_WINDOWS_H
#include <windows.h>
#endif

#if (defined(HAVE_LIBPTHREAD) && defined(HAVE_PTHREAD_H))
#define HAVE_PTHREAD 1
#include <pthread.h>
#endif

#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif

#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif

#ifdef HAVE_TIME_H
#include <time.h>
#endif

#include "locking.h"

PLock::PLock()
{
#ifdef HAVE_PTHREAD
    pthread_mutex_init(&lock, 0);
#elif defined(HAVE_WINDOWS_H)
    InitializeCriticalSection(&lock);
#endif
}

PLock::~PLock()
{
#ifdef HAVE_PTHREAD
    pthread_mutex_destroy(&lock);
#elif defined(HAVE_WINDOWS_H)
    DeleteCriticalSection(&lock);
#endif
}

void PLock::Lock(void)
{
#ifdef HAVE_PTHREAD
    pthread_mutex_lock(&lock);
#elif defined(HAVE_WINDOWS_H)
    EnterCriticalSection(&lock);
#endif
    // If we don't support threads this does nothing.
}

void PLock::Unlock(void)
{
#ifdef HAVE_PTHREAD
    pthread_mutex_unlock(&lock);
#elif defined(HAVE_WINDOWS_H)
    LeaveCriticalSection(&lock);
#endif
}

bool PLock::Trylock(void)
{
#ifdef HAVE_PTHREAD
    // Since we use normal mutexes this returns EBUSY if the
    // current thread owns the mutex.
    return pthread_mutex_trylock(&lock) != EBUSY;
#elif defined(HAVE_WINDOWS_H)
    // This is not implemented properly in Windows.  There is
    // TryEnterCriticalSection in Win NT and later but that
    // returns TRUE if the current thread owns the mutex.
    return false;
#endif
}

PCondVar::PCondVar()
{
#ifdef HAVE_PTHREAD
    pthread_cond_init(&cond, NULL);
#elif defined(HAVE_WINDOWS_H)
    // Create a manually set event initially set.
    cond = CreateEvent(NULL, TRUE, TRUE, NULL);
#endif
}

PCondVar::~PCondVar()
{
#ifdef HAVE_PTHREAD
    pthread_cond_destroy(&cond);
#elif defined(HAVE_WINDOWS_H)
    CloseHandle(cond);
#endif
}

// Wait indefinitely.  Drops the lock and reaquires it.
void PCondVar::Wait(PLock *pLock)
{
#ifdef HAVE_PTHREAD
    pthread_cond_wait(&cond, &pLock->lock);
#elif defined(HAVE_WINDOWS_H)
    // This code will NOT work as a general implementation of a
    // condition variable.  It works provided we use it carefully.
    // We only use this in the situation where all the threads
    // that can wait on this condvar have waited before we then
    // release all of them.
    ResetEvent(cond); // Do this with the lock held.
    // Can now release the lock.  It doesn't matter that releasing
    // the lock and waiting isn't atomic because the event is manually
    // reset.  If another thread sets the event before we call WFSO we'll
    // simply return immediately.
    LeaveCriticalSection(&pLock->lock);
    WaitForSingleObject(cond, INFINITE);
    EnterCriticalSection(&pLock->lock);
#endif
}

// Wait until a specified absolute time.  Drops the lock and reaquires it.
void PCondVar::WaitUntil(PLock *pLock, const void *timeArg)
{
#ifdef HAVE_PTHREAD
    pthread_cond_timedwait(&cond, &pLock->lock, (const struct timespec *)timeArg);
#elif defined(HAVE_WINDOWS_H)
    FILETIME now;
    FILETIME *time = (FILETIME *)timeArg;
    GetSystemTimeAsFileTime(&now);
    LARGE_INTEGER liNow, liTime;
    liNow.HighPart = now.dwHighDateTime;
    liNow.LowPart = now.dwLowDateTime;
    liTime.HighPart = time->dwHighDateTime;
    liTime.LowPart = time->dwLowDateTime;
    if (liNow.QuadPart >= liTime.QuadPart) // Already past the time
        return;
    DWORD toWait = (DWORD)((liTime.QuadPart - liNow.QuadPart) / (LONGLONG)10000);
    ResetEvent(cond); // Do this with the lock held.
    LeaveCriticalSection(&pLock->lock);
    WaitForSingleObject(cond, toWait);
    EnterCriticalSection(&pLock->lock);
#endif
}

// Wait for a number of milliseconds.  Used within the RTS.  Drops the lock and reaquires it.
bool PCondVar::WaitFor(PLock *pLock, unsigned milliseconds)
{
#ifdef HAVE_PTHREAD
    struct timespec waitTime;
    struct timeval tv;
    if (gettimeofday(&tv, NULL) != 0)
        return false;
    waitTime.tv_sec = tv.tv_sec + milliseconds / 1000;
    waitTime.tv_nsec = tv.tv_usec * 1000 + milliseconds % 1000;
    if (waitTime.tv_nsec >= 1000*1000*1000)
    {
        waitTime.tv_nsec -= 1000*1000*1000;
        waitTime.tv_sec += 1;
    }
    return pthread_cond_timedwait(&cond, &pLock->lock, &waitTime) == 0;
#elif defined(HAVE_WINDOWS_H)
    ResetEvent(cond); // Do this with the lock held.
    LeaveCriticalSection(&pLock->lock);
    DWORD dwResult = WaitForSingleObject(cond, milliseconds);
    EnterCriticalSection(&pLock->lock);
    return dwResult == WAIT_OBJECT_0;
#endif
}

// Wake up all the waiting threads.
void PCondVar::Signal(void)
{
#ifdef HAVE_PTHREAD
    pthread_cond_broadcast(&cond);
#elif defined(HAVE_WINDOWS_H)
    SetEvent(cond);
#endif
}

<commit_msg>Implement Trylock on Windows.  This uses TryEnterCriticalSection which is not available on Windows 95/98 etc. It may simply fail or may mean the code will not run at all.<commit_after>/*
    Title:      Mutex and Condition Variable library.

    Copyright (c) 2007 David C. J. Matthews

    Portions of this code are derived from the original stream io
    package copyright CUTS 1983-2000.

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

*/

#ifdef WIN32
#include "winconfig.h"
#else
#include "config.h"
#endif

#ifdef HAVE_WINDOWS_H
// We need the next define since TryEnterCriticalSection is only
// defined in Win NT.  This could mean that this code won't run under
// Windows 95 or 98.
#define _WIN32_WINNT 0x0400
#include <windows.h>
#endif

#if (defined(HAVE_LIBPTHREAD) && defined(HAVE_PTHREAD_H))
#define HAVE_PTHREAD 1
#include <pthread.h>
#endif

#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif

#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif

#ifdef HAVE_TIME_H
#include <time.h>
#endif

#include "locking.h"

PLock::PLock()
{
#ifdef HAVE_PTHREAD
    pthread_mutex_init(&lock, 0);
#elif defined(HAVE_WINDOWS_H)
    InitializeCriticalSection(&lock);
#endif
}

PLock::~PLock()
{
#ifdef HAVE_PTHREAD
    pthread_mutex_destroy(&lock);
#elif defined(HAVE_WINDOWS_H)
    DeleteCriticalSection(&lock);
#endif
}

void PLock::Lock(void)
{
#ifdef HAVE_PTHREAD
    pthread_mutex_lock(&lock);
#elif defined(HAVE_WINDOWS_H)
    EnterCriticalSection(&lock);
#endif
    // If we don't support threads this does nothing.
}

void PLock::Unlock(void)
{
#ifdef HAVE_PTHREAD
    pthread_mutex_unlock(&lock);
#elif defined(HAVE_WINDOWS_H)
    LeaveCriticalSection(&lock);
#endif
}

bool PLock::Trylock(void)
{
#ifdef HAVE_PTHREAD
    // Since we use normal mutexes this returns EBUSY if the
    // current thread owns the mutex.
    return pthread_mutex_trylock(&lock) != EBUSY;
#elif defined(HAVE_WINDOWS_H)
    // This is not implemented properly in Windows.  There is
    // TryEnterCriticalSection in Win NT and later but that
    // returns TRUE if the current thread owns the mutex.
   return TryEnterCriticalSection(&lock);
#endif
}

PCondVar::PCondVar()
{
#ifdef HAVE_PTHREAD
    pthread_cond_init(&cond, NULL);
#elif defined(HAVE_WINDOWS_H)
    // Create a manually set event initially set.
    cond = CreateEvent(NULL, TRUE, TRUE, NULL);
#endif
}

PCondVar::~PCondVar()
{
#ifdef HAVE_PTHREAD
    pthread_cond_destroy(&cond);
#elif defined(HAVE_WINDOWS_H)
    CloseHandle(cond);
#endif
}

// Wait indefinitely.  Drops the lock and reaquires it.
void PCondVar::Wait(PLock *pLock)
{
#ifdef HAVE_PTHREAD
    pthread_cond_wait(&cond, &pLock->lock);
#elif defined(HAVE_WINDOWS_H)
    // This code will NOT work as a general implementation of a
    // condition variable.  It works provided we use it carefully.
    // We only use this in the situation where all the threads
    // that can wait on this condvar have waited before we then
    // release all of them.
    ResetEvent(cond); // Do this with the lock held.
    // Can now release the lock.  It doesn't matter that releasing
    // the lock and waiting isn't atomic because the event is manually
    // reset.  If another thread sets the event before we call WFSO we'll
    // simply return immediately.
    LeaveCriticalSection(&pLock->lock);
    WaitForSingleObject(cond, INFINITE);
    EnterCriticalSection(&pLock->lock);
#endif
}

// Wait until a specified absolute time.  Drops the lock and reaquires it.
void PCondVar::WaitUntil(PLock *pLock, const void *timeArg)
{
#ifdef HAVE_PTHREAD
    pthread_cond_timedwait(&cond, &pLock->lock, (const struct timespec *)timeArg);
#elif defined(HAVE_WINDOWS_H)
    FILETIME now;
    FILETIME *time = (FILETIME *)timeArg;
    GetSystemTimeAsFileTime(&now);
    LARGE_INTEGER liNow, liTime;
    liNow.HighPart = now.dwHighDateTime;
    liNow.LowPart = now.dwLowDateTime;
    liTime.HighPart = time->dwHighDateTime;
    liTime.LowPart = time->dwLowDateTime;
    if (liNow.QuadPart >= liTime.QuadPart) // Already past the time
        return;
    DWORD toWait = (DWORD)((liTime.QuadPart - liNow.QuadPart) / (LONGLONG)10000);
    ResetEvent(cond); // Do this with the lock held.
    LeaveCriticalSection(&pLock->lock);
    WaitForSingleObject(cond, toWait);
    EnterCriticalSection(&pLock->lock);
#endif
}

// Wait for a number of milliseconds.  Used within the RTS.  Drops the lock and reaquires it.
bool PCondVar::WaitFor(PLock *pLock, unsigned milliseconds)
{
#ifdef HAVE_PTHREAD
    struct timespec waitTime;
    struct timeval tv;
    if (gettimeofday(&tv, NULL) != 0)
        return false;
    waitTime.tv_sec = tv.tv_sec + milliseconds / 1000;
    waitTime.tv_nsec = tv.tv_usec * 1000 + milliseconds % 1000;
    if (waitTime.tv_nsec >= 1000*1000*1000)
    {
        waitTime.tv_nsec -= 1000*1000*1000;
        waitTime.tv_sec += 1;
    }
    return pthread_cond_timedwait(&cond, &pLock->lock, &waitTime) == 0;
#elif defined(HAVE_WINDOWS_H)
    ResetEvent(cond); // Do this with the lock held.
    LeaveCriticalSection(&pLock->lock);
    DWORD dwResult = WaitForSingleObject(cond, milliseconds);
    EnterCriticalSection(&pLock->lock);
    return dwResult == WAIT_OBJECT_0;
#endif
}

// Wake up all the waiting threads.
void PCondVar::Signal(void)
{
#ifdef HAVE_PTHREAD
    pthread_cond_broadcast(&cond);
#elif defined(HAVE_WINDOWS_H)
    SetEvent(cond);
#endif
}

<|endoftext|>


<commit_before>
// Copyright (C) 2011 R. Keith Morley
//
// (MIT/X11 License)
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.

#include <Legion/Common/Util/Plugin.hpp>
#include <Legion/Common/Util/Assert.hpp>

#include <map>

using namespace legion;

class PluginManager::Impl
{
public:
    typedef ICamera*       (*CameraCreator       )( const Parameters& );
    typedef IFilm*         (*FilmCreator         )( const Parameters& );
    typedef IGeometry*     (*GeometryCreator     )( const Parameters& );
    typedef ILight*        (*LightCreator        )( const Parameters& );
    typedef ISurfaceShader*(*SurfaceShaderCreator)( const Parameters& );

    Impl() {}
    ~Impl() {}

    void registerCamera       ( const std::string& name, CameraCreator        );
    void registerFilm         ( const std::string& name, FilmCreator          );
    void registerGeometry     ( const std::string& name, GeometryCreator      );
    void registerLight        ( const std::string& name, LightCreator         );
    void registerSurfaceShader( const std::string& name, SurfaceShaderCreator );

    ICamera*  createCamera    ( const std::string& name, const Parameters& p );
    IFilm* createFilm         ( const std::string& name, const Parameters& p );
    IGeometry* createGeometry ( const std::string& name, const Parameters& p );
    ILight* createLight       ( const std::string& name, const Parameters& p );
    ISurfaceShader* createSurfaceShader( const std::string& name,
                                         const Parameters& p );

private:
    typedef std::map<std::string, CameraCreator>          CameraCreators;
    typedef std::map<std::string, FilmCreator>            FilmCreators;
    typedef std::map<std::string, GeometryCreator>        GeometryCreators;
    typedef std::map<std::string, LightCreator>           LightCreators;
    typedef std::map<std::string, SurfaceShaderCreator>   SurfaceShaderCreators;

    CameraCreators        m_camera_creators;
    FilmCreators          m_film_creators;
    GeometryCreators      m_geometry_creators;
    LightCreators         m_light_creators;
    SurfaceShaderCreators m_surface_shader_creators;
};

void PluginManager::Impl::registerCamera(
        const std::string& name,
        CameraCreator creator )
{
    LEGION_ASSERT( creator != 0 );
    LEGION_ASSERT( m_camera_creators.find( name ) != m_camera_creators.end() );

    m_camera_creators.insert( std::make_pair( name, creator ) );

}

void PluginManager::Impl::registerFilm(
        const std::string& name,
        FilmCreator creator )
{
    LEGION_TODO();
}

void PluginManager::Impl::registerGeometry(
        const std::string& name,
        GeometryCreator creator )
{
    LEGION_ASSERT( creator != 0 );
    LEGION_ASSERT( m_geometry_creators.count( name ) == 0 );

    m_geometry_creators.insert( std::make_pair( name, creator ) );
}

void PluginManager::Impl::registerLight(
        const std::string& name,
        LightCreator creator )
{
    LEGION_TODO();
}

void PluginManager::Impl::registerSurfaceShader(
        const std::string& name,
        SurfaceShaderCreator creator )
{
    LEGION_TODO();
}

ICamera* PluginManager::Impl::createCamera(
        const std::string& name,
        const Parameters& p )
{
    LEGION_TODO();
}

IFilm* PluginManager::Impl::createFilm(
        const std::string& name,
        const Parameters& p )
{
    LEGION_TODO();
}

IGeometry* PluginManager::Impl::createGeometry(
        const std::string& name,
        const Parameters& p )
{
    GeometryCreators::iterator it = m_geometry_creators.find( name );
    LEGION_ASSERT( it != m_geometry_creators.end() );

    return it->second( p );
}

ILight* PluginManager::Impl::createLight(
        const std::string& name,
        const Parameters& p )
{
    LEGION_TODO();
}

ISurfaceShader* PluginManager::Impl::createSurfaceShader(
        const std::string& name,
        const Parameters& p )
{
    LEGION_TODO();
}

//-----------------------------------------------------------------------------
//
// PluginManager
//
//-----------------------------------------------------------------------------
PluginManager::PluginManager()
    : m_impl( new Impl )
{
}

PluginManager::~PluginManager()
{
}

template <>
void PluginManager::registerPlugin<ICamera>(
        const std::string& name,
        ICamera* (*create)( const Parameters& params ) )
{
    m_impl->registerCamera( name, create );
}

template <>
void PluginManager::registerPlugin<IFilm>(
        const std::string& name,
        IFilm* (*create)( const Parameters& params ) )
{
    m_impl->registerFilm( name, create );
}

template <>
void PluginManager::registerPlugin<IGeometry>(
        const std::string& name,
        IGeometry* (*create)( const Parameters& params ) )
{
    m_impl->registerGeometry( name, create );
}

template <>
void PluginManager::registerPlugin<ILight>(
        const std::string& name,
        ILight* (*create)( const Parameters& params ) )
{
    m_impl->registerLight( name, create );
}

template <>
void PluginManager::registerPlugin<ISurfaceShader>(
        const std::string& name,
        ISurfaceShader* (*create)( const Parameters& params ) )
{
    m_impl->registerSurfaceShader( name, create );
}

template <>
ICamera* PluginManager::create<ICamera>(
        const std::string& plugin_name,
        const Parameters& params )
{
    return 0;
}

template <>
IFilm* PluginManager::create<IFilm>(
        const std::string& plugin_name,
        const Parameters& params )
{
    return 0;
}

template <>
IGeometry* PluginManager::create<IGeometry>(
        const std::string& plugin_name,
        const Parameters& params )
{
    return m_impl->createGeometry( plugin_name, params );
}

template <>
ILight* PluginManager::create<ILight>(
        const std::string& plugin_name,
        const Parameters& params )
{
    return 0;
}

template <>
ISurfaceShader* PluginManager::create<ISurfaceShader>(
        const std::string& plugin_name,
        const Parameters& params )
{
    return 0;
}
<commit_msg>Implementing stubbed functions in Plugin.cpp<commit_after>
// Copyright (C) 2011 R. Keith Morley
//
// (MIT/X11 License)
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.

#include <Legion/Common/Util/Plugin.hpp>
#include <Legion/Common/Util/Assert.hpp>

#include <map>

using namespace legion;

class PluginManager::Impl
{
public:
    typedef ICamera*       (*CameraCreator       )( const Parameters& );
    typedef IFilm*         (*FilmCreator         )( const Parameters& );
    typedef IGeometry*     (*GeometryCreator     )( const Parameters& );
    typedef ILight*        (*LightCreator        )( const Parameters& );
    typedef ISurfaceShader*(*SurfaceShaderCreator)( const Parameters& );

    Impl() {}
    ~Impl() {}

    void registerCamera       ( const std::string& name, CameraCreator        );
    void registerFilm         ( const std::string& name, FilmCreator          );
    void registerGeometry     ( const std::string& name, GeometryCreator      );
    void registerLight        ( const std::string& name, LightCreator         );
    void registerSurfaceShader( const std::string& name, SurfaceShaderCreator );

    ICamera*  createCamera    ( const std::string& name, const Parameters& p );
    IFilm* createFilm         ( const std::string& name, const Parameters& p );
    IGeometry* createGeometry ( const std::string& name, const Parameters& p );
    ILight* createLight       ( const std::string& name, const Parameters& p );
    ISurfaceShader* createSurfaceShader( const std::string& name,
                                         const Parameters& p );

private:
    typedef std::map<std::string, CameraCreator>          CameraCreators;
    typedef std::map<std::string, FilmCreator>            FilmCreators;
    typedef std::map<std::string, GeometryCreator>        GeometryCreators;
    typedef std::map<std::string, LightCreator>           LightCreators;
    typedef std::map<std::string, SurfaceShaderCreator>   SurfaceShaderCreators;

    CameraCreators        m_camera_creators;
    FilmCreators          m_film_creators;
    GeometryCreators      m_geometry_creators;
    LightCreators         m_light_creators;
    SurfaceShaderCreators m_surface_shader_creators;
};

void PluginManager::Impl::registerCamera(
        const std::string& name,
        CameraCreator creator )
{
    LEGION_ASSERT( creator != 0 );
    LEGION_ASSERT( m_camera_creators.find( name ) != m_camera_creators.end() );

    m_camera_creators.insert( std::make_pair( name, creator ) );
}

void PluginManager::Impl::registerFilm(
        const std::string& name,
        FilmCreator creator )
{
    LEGION_ASSERT( creator != 0 );
    LEGION_ASSERT( m_film_creators.find( name ) != m_film_creators.end() );

    m_film_creators.insert( std::make_pair( name, creator ) );
}

void PluginManager::Impl::registerGeometry(
        const std::string& name,
        GeometryCreator creator )
{
    LEGION_ASSERT( creator != 0 );
    LEGION_ASSERT( m_geometry_creators.count( name ) == 0 );

    m_geometry_creators.insert( std::make_pair( name, creator ) );
}

void PluginManager::Impl::registerLight(
        const std::string& name,
        LightCreator creator )
{
    LEGION_ASSERT( creator != 0 );
    LEGION_ASSERT( m_light_creators.find( name ) != m_light_creators.end() );

    m_light_creators.insert( std::make_pair( name, creator ) );
}

void PluginManager::Impl::registerSurfaceShader(
        const std::string& name,
        SurfaceShaderCreator creator )
{
    LEGION_ASSERT( creator != 0 );
    LEGION_ASSERT( m_surface_shader_creators.find( name ) !=
                   m_surface_shader_creators.end() );

    m_surface_shader_creators.insert( std::make_pair( name, creator ) );
}

ICamera* PluginManager::Impl::createCamera(
        const std::string& name,
        const Parameters& p )
{
    CameraCreators::iterator it = m_camera_creators.find( name );
    LEGION_ASSERT( it != m_camera_creators.end() );

    return it->second( p );
}

IFilm* PluginManager::Impl::createFilm(
        const std::string& name,
        const Parameters& p )
{
    FilmCreators::iterator it = m_film_creators.find( name );
    LEGION_ASSERT( it != m_film_creators.end() );

    return it->second( p );
}

IGeometry* PluginManager::Impl::createGeometry(
        const std::string& name,
        const Parameters& p )
{
    GeometryCreators::iterator it = m_geometry_creators.find( name );
    LEGION_ASSERT( it != m_geometry_creators.end() );

    return it->second( p );
}

ILight* PluginManager::Impl::createLight(
        const std::string& name,
        const Parameters& p )
{
    LightCreators::iterator it = m_light_creators.find( name );
    LEGION_ASSERT( it != m_light_creators.end() );

    return it->second( p );
}

ISurfaceShader* PluginManager::Impl::createSurfaceShader(
        const std::string& name,
        const Parameters& p )
{
    SurfaceShaderCreators::iterator it = m_surface_shader_creators.find( name );
    LEGION_ASSERT( it != m_surface_shader_creators.end() );

    return it->second( p );
}

//-----------------------------------------------------------------------------
//
// PluginManager
//
//-----------------------------------------------------------------------------
PluginManager::PluginManager()
    : m_impl( new Impl )
{
}

PluginManager::~PluginManager()
{
}

template <>
void PluginManager::registerPlugin<ICamera>(
        const std::string& name,
        ICamera* (*create)( const Parameters& params ) )
{
    m_impl->registerCamera( name, create );
}

template <>
void PluginManager::registerPlugin<IFilm>(
        const std::string& name,
        IFilm* (*create)( const Parameters& params ) )
{
    m_impl->registerFilm( name, create );
}

template <>
void PluginManager::registerPlugin<IGeometry>(
        const std::string& name,
        IGeometry* (*create)( const Parameters& params ) )
{
    m_impl->registerGeometry( name, create );
}

template <>
void PluginManager::registerPlugin<ILight>(
        const std::string& name,
        ILight* (*create)( const Parameters& params ) )
{
    m_impl->registerLight( name, create );
}

template <>
void PluginManager::registerPlugin<ISurfaceShader>(
        const std::string& name,
        ISurfaceShader* (*create)( const Parameters& params ) )
{
    m_impl->registerSurfaceShader( name, create );
}

template <>
ICamera* PluginManager::create<ICamera>(
        const std::string& plugin_name,
        const Parameters& params )
{
    return m_impl->createCamera( plugin_name, params );
}

template <>
IFilm* PluginManager::create<IFilm>(
        const std::string& plugin_name,
        const Parameters& params )
{
    return m_impl->createFilm( plugin_name, params );
}

template <>
IGeometry* PluginManager::create<IGeometry>(
        const std::string& plugin_name,
        const Parameters& params )
{
    return m_impl->createGeometry( plugin_name, params );
}

template <>
ILight* PluginManager::create<ILight>(
        const std::string& plugin_name,
        const Parameters& params )
{
    return m_impl->createLight( plugin_name, params );
}

template <>
ISurfaceShader* PluginManager::create<ISurfaceShader>(
        const std::string& plugin_name,
        const Parameters& params )
{
    return m_impl->createSurfaceShader( plugin_name, params );
}
<|endoftext|>