<commit_before>/*
Copyright 2013, Jernej Kovacic

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.
*/

/**
 * @file
 * @author Jernej Kovacic
 *
 * Implementation of functions within namespace LinearEquationSolver.
 */

// no #include "LinearEquationSolverGeneric.hpp" !!!
#include <cstddef>
#include <algorithm>

#include "exception/MatrixException.hpp"
#include "util/NumericUtil.hpp"
#include "matrix/MatrixGeneric.hpp"
#include "matrix/SqMatrixGeneric.hpp"
#include "../settings/omp_settings.h"

/**
 * Solves the system of linear equations and returns its unique solution if it exists.
 *
 * Number of coef's columns must be equal to the number of term's rows.
 *
 * If unique solution does not exist (i.e. determinant of 'coef' is 0), an
 * exception will be thrown.
 *
 * @param coef - a square matrix with coefficients of the system of linear equations
 * @param term - a matrix with constant terms of the system of linear equations
 * @param sol - a reference to a matrix to be assigned the solution of equations
 *
 * @throw LinearEquationSolverException if a unique solution cannot be found for any reason
 */
template <class T>
void math::LinearEquationSolver::solve(
          const math::SqMatrixGeneric<T>& coef,
          const math::MatrixGeneric<T>& term,
          math::MatrixGeneric<T>& sol
        ) throw (math::LinearEquationSolverException)
{
    /*
     * The Gaussian elimination algorithm is implemented:
     * multiples of coef's and term's lines are added to other lines until
     * "coef" appears as a unit matrix. In this case the modified "term" is a
     * unique solution of a system of linear equations. More details about
     * the algorithm at: http://en.wikipedia.org/wiki/Gaussian_elimination
     */
    const size_t N = coef.nrColumns();          // Nr. of unknowns
    const size_t NT = term.nrColumns();         // Nr. of terms' columns
    const size_t Nmax = std::max(N, NT);        // max. of both values

    // Check of dimensions
    if ( N != term.nrRows() )
    {
        throw math::LinearEquationSolverException(math::LinearEquationSolverException::INVALID_DIMENSION);
    }

    try
    {
        math::SqMatrixGeneric<T> temp(coef);
        sol = term;

        // Try to convert the 'temp' into an identity matrix
        // by appropriately adding multiples of other lines to each line
        // (incl. lines of 'retVal')

        /*
         * The first part of the algorithm will (try to) ensure there are
         * no zeros among temp's diagonal elements. Additionally it will
         * subtract multiples of the i.th row from all subsequent rows (r>i)
         * so their i.th column will be equal to 0. This requires plenty of
         * additions/subtractions of individual rows so parallelization of
         * this for loop is not possible due to race conditions. It will be
         * possible to parallelize certain parts of this loop, though.
         */
        for ( size_t i=0; i<N; ++i )
        {
            // first check if the diagonal element equals 0
            if ( true == math::NumericUtil::isZero<T>(temp.at(i, i)) )
            {
                size_t r;

                // if it does, try to find another row r where temp(r,i)!=0
                for ( r=0; r<N; ++r )
                {
                    if ( r==i )
                    {
                        // it is known in advance, that temp(i,i)==0, so skip it
                        continue;  // for r
                    }

                    if ( false == math::NumericUtil::isZero<T>(temp.at(r, i)) )
                    {
                        // found, no need to search further
                        break;  // out of for r
                    }
                }  // for r

                if ( N==r )
                {
                    // No temp(r,i)!=0 was found, the matrix 'temp' is non-invertible.
                    // Throw an exception
                    throw math::LinearEquationSolverException(math::LinearEquationSolverException::NO_UNIQUE_SOLUTION);
                }

                // add the r.th line to the i.th one and thus prevent temp(i,i) from being 0:

                #pragma omp parallel for default(none) shared(temp, sol, i, r)
                for ( size_t c=0; c<Nmax; ++c )
                {
                    if ( c<N )
                    {
                        temp.at(i, c) += temp.at(r, c);
                    }

                    if ( c<NT )
                    {
                        sol.at(i, c) += sol.at(r, c);
                    }
                }

            }  // if temp(i,i)==0

            // Set the i.th column of all other rows (r>i) to 0 by
            // adding the appropriate multiple of the i.th row
            #pragma omp parallel for default(none) shared(temp, sol, i)
            for ( size_t r=i+1; r<N; r++ )
            {
                // Nothing to do if temp(r,i) is already 0.
                if ( false == math::NumericUtil::isZero<T>(temp.at(r, i)) )
                {
                    // Subtract a multiple of the i^th row.
                    const T el = temp.get(r, i) / temp.get(i, i);

                    // temp(r,:) = temp(r,:)-el*temp(i,:)
                    for ( size_t c=i; c<N; ++c )
                    {
                        temp.at(r, c) -= el*temp.at(i, c);
                    }

                    // term(r,:) = term(r,:)-el*term(i,:)
                    for ( size_t c=0; c<NT; ++c )
                    {
                        sol.at(r, c) -= el * sol.at(i, c);
                    }
                }  // if (temp(r,i) != 0
            }  // for r
        }  // for i

        // Set the diag elements of 'temp' and 'retVal' to 1 by dividing the
        // whole row by temp(r,r). Columns smaller than 'r' are already equal to 0.

        // Normalizing of each row is independent from other rows so it is
        // perfectly safe to parallelize the task by rows.
        #pragma omp parallel for default(none) shared(temp, sol)
        for ( size_t r=0; r<N; ++r )
        {
            const T el = temp.get(r, r);

            for ( size_t c=r; c<N; ++c )
            {
                temp.at(r, c) /= el;
            }

            for ( size_t c=0; c<NT; ++c )
            {
                sol.at(r, c) /= el;
            }
        }

        // Now the lower triangle (below diag excl.) is 0, the diagonal consists of 1,
        // The upper triangle (above the diag) must be set to 0 as well.

        // Column 'c' of each row (for r<c) will be set to 0
        // by adding the appropriate multiple of c.th row

        // Parallelization of this for loop is not possible due to race conditions.
        for ( size_t c=1; c<N; ++c )
        {
            // The current row to apply the operation described above

            // It is possible to parallelize this for loop because a row 'c' (not included
            // into the for loop) will be added independently to each "parallelized" row
            // 'r' (between 0 and c-1 incl.), thus no race condition is possible.
            #pragma omp parallel for \
                        default(none) \
                        shared(temp, sol, c) \
                        schedule(dynamic)
            for ( size_t r=0; r<c; ++r )
            {
                // Nothing to do if temp(r,c) already equals 0
                if ( false == math::NumericUtil::isZero<T>(temp.at(r, c)) )
                {
                	// To set temp(r,c) to 0 it is a good idea to add the c.th row to it.
                    // temp(c,i); i<c are already 0 (i.e. will not affect anything left of temp(i,c)
                    // and temp(c,c) is already 1.

                    const T el = temp.get(r, c);

                    // temp(r,:) = temp(r,:) - el*temp(c,:)
                    for ( size_t i=c; i<N; ++i )
                    {
                        temp.at(r, i) -= el * temp.at(c, i);
                    }

                    // term(r,:) = term(r,:) - el*term(c,:)
                    for ( size_t i=0; i<NT; ++i )
                    {
                        sol.at(r, i) -= el * sol.at(c, i);
                    }
                }  // if temp(r,c) != 0
            }  // for r
        }  // for c

    }  // try
    catch ( const math::MatrixException& mex )
    {
        throw math::LinearEquationSolverException(math::LinearEquationSolverException::OUT_OF_MEMORY);
    }

}
<commit_msg>reformatted comments in lineq algorithms<commit_after>/*
Copyright 2013, Jernej Kovacic

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.
*/

/**
 * @file
 * @author Jernej Kovacic
 *
 * Implementation of functions within namespace LinearEquationSolver.
 */

// no #include "LinearEquationSolverGeneric.hpp" !!!
#include <cstddef>
#include <algorithm>

#include "exception/MatrixException.hpp"
#include "util/NumericUtil.hpp"
#include "matrix/MatrixGeneric.hpp"
#include "matrix/SqMatrixGeneric.hpp"
#include "../settings/omp_settings.h"

/**
 * Solves the system of linear equations and returns its unique solution if it exists.
 *
 * Number of coef's columns must be equal to the number of term's rows.
 *
 * If unique solution does not exist (i.e. determinant of 'coef' is 0), an
 * exception will be thrown.
 *
 * @param coef - a square matrix with coefficients of the system of linear equations
 * @param term - a matrix with constant terms of the system of linear equations
 * @param sol - a reference to a matrix to be assigned the solution of equations
 *
 * @throw LinearEquationSolverException if a unique solution cannot be found for any reason
 */
template <class T>
void math::LinearEquationSolver::solve(
          const math::SqMatrixGeneric<T>& coef,
          const math::MatrixGeneric<T>& term,
          math::MatrixGeneric<T>& sol
        ) throw (math::LinearEquationSolverException)
{
    /*
     * The Gaussian elimination algorithm is implemented:
     * multiples of coef's and term's lines are added to other lines until
     * "coef" appears as a unit matrix. In this case the modified "term" is a
     * unique solution of a system of linear equations. More details about
     * the algorithm at: http://en.wikipedia.org/wiki/Gaussian_elimination
     */
    const size_t N = coef.nrColumns();          // Nr. of unknowns
    const size_t NT = term.nrColumns();         // Nr. of terms' columns
    const size_t Nmax = std::max(N, NT);        // max. of both values

    // Check of dimensions
    if ( N != term.nrRows() )
    {
        throw math::LinearEquationSolverException(math::LinearEquationSolverException::INVALID_DIMENSION);
    }

    try
    {
        math::SqMatrixGeneric<T> temp(coef);
        sol = term;

        /*
         * Try to convert the 'temp' into an identity matrix
         * by appropriately adding multiples of other lines to each line
         * (incl. lines of 'retVal')
         */

        /*
         * The first part of the algorithm will (try to) ensure there are
         * no zeros among temp's diagonal elements. Additionally it will
         * subtract multiples of the i.th row from all subsequent rows (r>i)
         * so their i.th column will be equal to 0. This requires plenty of
         * additions/subtractions of individual rows so parallelization of
         * this for loop is not possible due to race conditions. It will be
         * possible to parallelize certain parts of this loop, though.
         */
        for ( size_t i=0; i<N; ++i )
        {
            // first check if the diagonal element equals 0
            if ( true == math::NumericUtil::isZero<T>(temp.at(i, i)) )
            {
                size_t r;

                // if it does, try to find another row r where temp(r,i)!=0
                for ( r=0; r<N; ++r )
                {
                    if ( r==i )
                    {
                        // it is known in advance, that temp(i,i)==0, so skip it
                        continue;  // for r
                    }

                    if ( false == math::NumericUtil::isZero<T>(temp.at(r, i)) )
                    {
                        // found, no need to search further
                        break;  // out of for r
                    }
                }  // for r

                if ( N==r )
                {
                    // No temp(r,i)!=0 was found, the matrix 'temp' is non-invertible.
                    // Throw an exception
                    throw math::LinearEquationSolverException(math::LinearEquationSolverException::NO_UNIQUE_SOLUTION);
                }

                // add the r.th line to the i.th one and thus prevent temp(i,i) from being 0:

                #pragma omp parallel for default(none) shared(temp, sol, i, r)
                for ( size_t c=0; c<Nmax; ++c )
                {
                    if ( c<N )
                    {
                        temp.at(i, c) += temp.at(r, c);
                    }

                    if ( c<NT )
                    {
                        sol.at(i, c) += sol.at(r, c);
                    }
                }

            }  // if temp(i,i)==0

            // Set the i.th column of all other rows (r>i) to 0 by
            // adding the appropriate multiple of the i.th row
            #pragma omp parallel for default(none) shared(temp, sol, i)
            for ( size_t r=i+1; r<N; r++ )
            {
                // Nothing to do if temp(r,i) is already 0.
                if ( false == math::NumericUtil::isZero<T>(temp.at(r, i)) )
                {
                    // Subtract a multiple of the i^th row.
                    const T el = temp.get(r, i) / temp.get(i, i);

                    // temp(r,:) = temp(r,:)-el*temp(i,:)
                    for ( size_t c=i; c<N; ++c )
                    {
                        temp.at(r, c) -= el*temp.at(i, c);
                    }

                    // term(r,:) = term(r,:)-el*term(i,:)
                    for ( size_t c=0; c<NT; ++c )
                    {
                        sol.at(r, c) -= el * sol.at(i, c);
                    }
                }  // if (temp(r,i) != 0
            }  // for r
        }  // for i

        /*
         * Set the diag elements of 'temp' and 'retVal' to 1 by dividing the
         * whole row by temp(r,r). Columns smaller than 'r' are already equal to 0.
         */

        /*
         * Normalizing of each row is independent from other rows so it is
         * perfectly safe to parallelize the task by rows.
         */
        #pragma omp parallel for default(none) shared(temp, sol)
        for ( size_t r=0; r<N; ++r )
        {
            const T el = temp.get(r, r);

            for ( size_t c=r; c<N; ++c )
            {
                temp.at(r, c) /= el;
            }

            for ( size_t c=0; c<NT; ++c )
            {
                sol.at(r, c) /= el;
            }
        }

        /*
         * Now the lower triangle (below diag excl.) is 0, the diagonal consists of 1,
         * The upper triangle (above the diag) must be set to 0 as well.
         *
         * Column 'c' of each row (for r<c) will be set to 0
         * by adding the appropriate multiple of c.th row
         *
         * Parallelization of this for loop is not possible due to race conditions.
         */
        for ( size_t c=1; c<N; ++c )
        {
            // The current row to apply the operation described above

            /*
             * It is possible to parallelize this for loop because a row 'c' (not included
             * into the for loop) will be added independently to each "parallelized" row
             * 'r' (between 0 and c-1 incl.), thus no race condition is possible.
             */
            #pragma omp parallel for \
                        default(none) \
                        shared(temp, sol, c) \
                        schedule(dynamic)
            for ( size_t r=0; r<c; ++r )
            {
                // Nothing to do if temp(r,c) already equals 0
                if ( false == math::NumericUtil::isZero<T>(temp.at(r, c)) )
                {
                    /*
                     * To set temp(r,c) to 0 it is a good idea to add the c.th row to it.
                     * temp(c,i); i<c are already 0 (i.e. will not affect anything left of temp(i,c)
                     * and temp(c,c) is already 1.
                     */

                    const T el = temp.get(r, c);

                    // temp(r,:) = temp(r,:) - el*temp(c,:)
                    for ( size_t i=c; i<N; ++i )
                    {
                        temp.at(r, i) -= el * temp.at(c, i);
                    }

                    // term(r,:) = term(r,:) - el*term(c,:)
                    for ( size_t i=0; i<NT; ++i )
                    {
                        sol.at(r, i) -= el * sol.at(c, i);
                    }
                }  // if temp(r,c) != 0
            }  // for r
        }  // for c

    }  // try
    catch ( const math::MatrixException& mex )
    {
        throw math::LinearEquationSolverException(math::LinearEquationSolverException::OUT_OF_MEMORY);
    }

}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: DAVResourceAccess.hxx,v $
 *
 *  $Revision: 1.15 $
 *
 *  last change: $Author: kz $ $Date: 2006-12-13 15:04:16 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    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., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef _DAVRESOURCEACCESS_HXX_
#define _DAVRESOURCEACCESS_HXX_

#include <vector>

#ifndef _RTL_USTRING_HXX_
#include <rtl/ustring.hxx>
#endif
#ifndef _RTL_REF_HXX_
#include <rtl/ref.hxx>
#endif

#ifndef _OSL_MUTEX_HXX_
#include <osl/mutex.hxx>
#endif

#ifndef _COM_SUN_STAR_IO_XINPUTSTREAM_HPP_
#include <com/sun/star/io/XInputStream.hpp>
#endif
#ifndef _COM_SUN_STAR_IO_XOUTPUTSTREAM_HPP_
#include <com/sun/star/io/XOutputStream.hpp>
#endif
#ifndef _COM_SUN_STAR_UCB_LOCK_HPP_
#include <com/sun/star/ucb/Lock.hpp>
#endif
#ifndef _COM_SUN_STAR_UCB_XCOMMANDENVIRONMENT_HPP_
#include <com/sun/star/ucb/XCommandEnvironment.hpp>
#endif

#ifndef _DAVAUTHLISTENER_HXX_
#include "DAVAuthListener.hxx"
#endif
#ifndef _DAVEXCEPTION_HXX_
#include "DAVException.hxx"
#endif
#ifndef _DAVSESSION_HXX_
#include "DAVSession.hxx"
#endif
#ifndef _DAVRESOURCE_HXX_
#include "DAVResource.hxx"
#endif
#ifndef _DAVTYPES_HXX_
#include "DAVTypes.hxx"
#endif
#ifndef _NEONURI_HXX_
#include "NeonUri.hxx"
#endif

namespace webdav_ucp
{

class DAVSessionFactory;

class DAVResourceAccess
{
    osl::Mutex    m_aMutex;
    rtl::OUString m_aURL;
    rtl::OUString m_aPath;
    rtl::Reference< DAVSession > m_xSession;
    rtl::Reference< DAVSessionFactory > m_xSessionFactory;
    com::sun::star::uno::Reference<
    com::sun::star::lang::XMultiServiceFactory > m_xSMgr;
    std::vector< NeonUri > m_aRedirectURIs;

public:
    DAVResourceAccess() : m_xSessionFactory( 0 ) {}
    DAVResourceAccess( const com::sun::star::uno::Reference<
               com::sun::star::lang::XMultiServiceFactory > & rSMgr,
                       rtl::Reference<
                   DAVSessionFactory > const & rSessionFactory,
                       const rtl::OUString & rURL );
    DAVResourceAccess( const DAVResourceAccess & rOther );

    DAVResourceAccess & operator=( const DAVResourceAccess & rOther );

    void setURL( const rtl::OUString & rNewURL )
    throw( DAVException );

    const rtl::OUString & getURL() const { return m_aURL; }

    rtl::Reference< DAVSessionFactory > getSessionFactory() const
    { return m_xSessionFactory; }

    // DAV methods
    //

    void
    OPTIONS(  DAVCapabilities & rCapabilities,
          const com::sun::star::uno::Reference<
              com::sun::star::ucb::XCommandEnvironment > & xEnv )
    throw( DAVException );

    // allprop & named
    void
    PROPFIND( const Depth nDepth,
          const std::vector< rtl::OUString > & rPropertyNames,
          std::vector< DAVResource > & rResources,
          const com::sun::star::uno::Reference<
              com::sun::star::ucb::XCommandEnvironment > & xEnv )
    throw( DAVException );

    // propnames
    void
    PROPFIND( const Depth nDepth,
          std::vector< DAVResourceInfo > & rResInfo,
          const com::sun::star::uno::Reference<
              com::sun::star::ucb::XCommandEnvironment > & xEnv )
    throw( DAVException );

    void
    PROPPATCH( const std::vector< ProppatchValue > & rValues,
           const com::sun::star::uno::Reference<
               com::sun::star::ucb::XCommandEnvironment >& xEnv )
    throw( DAVException );

    void
    HEAD( const std::vector< rtl::OUString > & rHeaderNames, // empty == 'all'
          DAVResource & rResource,
          const com::sun::star::uno::Reference<
          com::sun::star::ucb::XCommandEnvironment >& xEnv )
        throw( DAVException );

    com::sun::star::uno::Reference< com::sun::star::io::XInputStream >
    GET( const com::sun::star::uno::Reference<
         com::sun::star::ucb::XCommandEnvironment > & xEnv )
    throw( DAVException );

    void
    GET( com::sun::star::uno::Reference<
         com::sun::star::io::XOutputStream > & rStream,
         const com::sun::star::uno::Reference<
         com::sun::star::ucb::XCommandEnvironment > & xEnv )
        throw( DAVException );

    com::sun::star::uno::Reference< com::sun::star::io::XInputStream >
    GET( const std::vector< rtl::OUString > & rHeaderNames, // empty == 'all'
         DAVResource & rResource,
         const com::sun::star::uno::Reference<
         com::sun::star::ucb::XCommandEnvironment > & xEnv )
        throw( DAVException );

    void
    GET( com::sun::star::uno::Reference<
         com::sun::star::io::XOutputStream > & rStream,
         const std::vector< rtl::OUString > & rHeaderNames, // empty == 'all'
         DAVResource & rResource,
         const com::sun::star::uno::Reference<
         com::sun::star::ucb::XCommandEnvironment > & xEnv )
        throw( DAVException );

    void
    PUT( const com::sun::star::uno::Reference<
         com::sun::star::io::XInputStream > & rStream,
     const com::sun::star::uno::Reference<
         com::sun::star::ucb::XCommandEnvironment > & xEnv )
    throw( DAVException );

    com::sun::star::uno::Reference< com::sun::star::io::XInputStream >
    POST( const rtl::OUString & rContentType,
      const rtl::OUString & rReferer,
      const com::sun::star::uno::Reference<
          com::sun::star::io::XInputStream > & rInputStream,
      const com::sun::star::uno::Reference<
          com::sun::star::ucb::XCommandEnvironment >& xEnv )
        throw ( DAVException );

    void
    POST( const rtl::OUString & rContentType,
      const rtl::OUString & rReferer,
      const com::sun::star::uno::Reference<
          com::sun::star::io::XInputStream > & rInputStream,
      com::sun::star::uno::Reference<
          com::sun::star::io::XOutputStream > & rOutputStream,
      const com::sun::star::uno::Reference<
          com::sun::star::ucb::XCommandEnvironment >& xEnv )
        throw ( DAVException );

    void
    MKCOL( const com::sun::star::uno::Reference<
           com::sun::star::ucb::XCommandEnvironment > & xEnv )
    throw( DAVException );

    void
    COPY( const ::rtl::OUString & rSourcePath,
      const ::rtl::OUString & rDestinationURI,
      sal_Bool bOverwrite,
      const com::sun::star::uno::Reference<
          com::sun::star::ucb::XCommandEnvironment > & xEnv )
    throw( DAVException );

    void
    MOVE( const ::rtl::OUString & rSourcePath,
      const ::rtl::OUString & rDestinationURI,
      sal_Bool bOverwrite,
      const com::sun::star::uno::Reference<
          com::sun::star::ucb::XCommandEnvironment > & xEnv )
    throw( DAVException );

    void
    DESTROY( const com::sun::star::uno::Reference<
              com::sun::star::ucb::XCommandEnvironment > & xEnv )
    throw( DAVException );

    void
    LOCK( const com::sun::star::ucb::Lock & rLock,
      const com::sun::star::uno::Reference<
          com::sun::star::ucb::XCommandEnvironment > & xEnv )
    throw( DAVException );

    void
    UNLOCK( const com::sun::star::ucb::Lock & rLock,
        const com::sun::star::uno::Reference<
            com::sun::star::ucb::XCommandEnvironment > & xEnv )
    throw( DAVException );

    // helper
    static void getUserRequestHeaders(
    const com::sun::star::uno::Reference<
        com::sun::star::ucb::XCommandEnvironment > & xEnv,
    const rtl::OUString & rURI,
    const rtl::OUString & rMethod,
    DAVRequestHeaders & rRequestHeaders );

private:
    const rtl::OUString & getRequestURI() const;
    sal_Bool detectRedirectCycle( const rtl::OUString& rRedirectURL );
    sal_Bool handleException( DAVException & e );
    void initialize()
        throw ( DAVException );
};

} // namespace webdav_ucp

#endif // _DAVRESOURCEACCESS_HXX_
<commit_msg>INTEGRATION: CWS ucbfixes01 (1.15.24); FILE MERGED 2007/04/18 15:34:05 kso 1.15.24.1: #134089# - Never allow URLs with empty hostnames.<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: DAVResourceAccess.hxx,v $
 *
 *  $Revision: 1.16 $
 *
 *  last change: $Author: kz $ $Date: 2007-05-10 13:07:00 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    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., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef _DAVRESOURCEACCESS_HXX_
#define _DAVRESOURCEACCESS_HXX_

#include <vector>

#ifndef _RTL_USTRING_HXX_
#include <rtl/ustring.hxx>
#endif
#ifndef _RTL_REF_HXX_
#include <rtl/ref.hxx>
#endif

#ifndef _OSL_MUTEX_HXX_
#include <osl/mutex.hxx>
#endif

#ifndef _COM_SUN_STAR_IO_XINPUTSTREAM_HPP_
#include <com/sun/star/io/XInputStream.hpp>
#endif
#ifndef _COM_SUN_STAR_IO_XOUTPUTSTREAM_HPP_
#include <com/sun/star/io/XOutputStream.hpp>
#endif
#ifndef _COM_SUN_STAR_UCB_LOCK_HPP_
#include <com/sun/star/ucb/Lock.hpp>
#endif
#ifndef _COM_SUN_STAR_UCB_XCOMMANDENVIRONMENT_HPP_
#include <com/sun/star/ucb/XCommandEnvironment.hpp>
#endif

#ifndef _DAVAUTHLISTENER_HXX_
#include "DAVAuthListener.hxx"
#endif
#ifndef _DAVEXCEPTION_HXX_
#include "DAVException.hxx"
#endif
#ifndef _DAVSESSION_HXX_
#include "DAVSession.hxx"
#endif
#ifndef _DAVRESOURCE_HXX_
#include "DAVResource.hxx"
#endif
#ifndef _DAVTYPES_HXX_
#include "DAVTypes.hxx"
#endif
#ifndef _NEONURI_HXX_
#include "NeonUri.hxx"
#endif

namespace webdav_ucp
{

class DAVSessionFactory;

class DAVResourceAccess
{
    osl::Mutex    m_aMutex;
    rtl::OUString m_aURL;
    rtl::OUString m_aPath;
    rtl::Reference< DAVSession > m_xSession;
    rtl::Reference< DAVSessionFactory > m_xSessionFactory;
    com::sun::star::uno::Reference<
    com::sun::star::lang::XMultiServiceFactory > m_xSMgr;
    std::vector< NeonUri > m_aRedirectURIs;

public:
    DAVResourceAccess() : m_xSessionFactory( 0 ) {}
    DAVResourceAccess( const com::sun::star::uno::Reference<
               com::sun::star::lang::XMultiServiceFactory > & rSMgr,
                       rtl::Reference<
                   DAVSessionFactory > const & rSessionFactory,
                       const rtl::OUString & rURL );
    DAVResourceAccess( const DAVResourceAccess & rOther );

    DAVResourceAccess & operator=( const DAVResourceAccess & rOther );

    void setURL( const rtl::OUString & rNewURL )
    throw( DAVException );

    const rtl::OUString & getURL() const { return m_aURL; }

    rtl::Reference< DAVSessionFactory > getSessionFactory() const
    { return m_xSessionFactory; }

    // DAV methods
    //

    void
    OPTIONS(  DAVCapabilities & rCapabilities,
          const com::sun::star::uno::Reference<
              com::sun::star::ucb::XCommandEnvironment > & xEnv )
    throw( DAVException );

    // allprop & named
    void
    PROPFIND( const Depth nDepth,
          const std::vector< rtl::OUString > & rPropertyNames,
          std::vector< DAVResource > & rResources,
          const com::sun::star::uno::Reference<
              com::sun::star::ucb::XCommandEnvironment > & xEnv )
    throw( DAVException );

    // propnames
    void
    PROPFIND( const Depth nDepth,
          std::vector< DAVResourceInfo > & rResInfo,
          const com::sun::star::uno::Reference<
              com::sun::star::ucb::XCommandEnvironment > & xEnv )
    throw( DAVException );

    void
    PROPPATCH( const std::vector< ProppatchValue > & rValues,
           const com::sun::star::uno::Reference<
               com::sun::star::ucb::XCommandEnvironment >& xEnv )
    throw( DAVException );

    void
    HEAD( const std::vector< rtl::OUString > & rHeaderNames, // empty == 'all'
          DAVResource & rResource,
          const com::sun::star::uno::Reference<
          com::sun::star::ucb::XCommandEnvironment >& xEnv )
        throw( DAVException );

    com::sun::star::uno::Reference< com::sun::star::io::XInputStream >
    GET( const com::sun::star::uno::Reference<
         com::sun::star::ucb::XCommandEnvironment > & xEnv )
    throw( DAVException );

    void
    GET( com::sun::star::uno::Reference<
         com::sun::star::io::XOutputStream > & rStream,
         const com::sun::star::uno::Reference<
         com::sun::star::ucb::XCommandEnvironment > & xEnv )
        throw( DAVException );

    com::sun::star::uno::Reference< com::sun::star::io::XInputStream >
    GET( const std::vector< rtl::OUString > & rHeaderNames, // empty == 'all'
         DAVResource & rResource,
         const com::sun::star::uno::Reference<
         com::sun::star::ucb::XCommandEnvironment > & xEnv )
        throw( DAVException );

    void
    GET( com::sun::star::uno::Reference<
         com::sun::star::io::XOutputStream > & rStream,
         const std::vector< rtl::OUString > & rHeaderNames, // empty == 'all'
         DAVResource & rResource,
         const com::sun::star::uno::Reference<
         com::sun::star::ucb::XCommandEnvironment > & xEnv )
        throw( DAVException );

    void
    PUT( const com::sun::star::uno::Reference<
         com::sun::star::io::XInputStream > & rStream,
     const com::sun::star::uno::Reference<
         com::sun::star::ucb::XCommandEnvironment > & xEnv )
    throw( DAVException );

    com::sun::star::uno::Reference< com::sun::star::io::XInputStream >
    POST( const rtl::OUString & rContentType,
      const rtl::OUString & rReferer,
      const com::sun::star::uno::Reference<
          com::sun::star::io::XInputStream > & rInputStream,
      const com::sun::star::uno::Reference<
          com::sun::star::ucb::XCommandEnvironment >& xEnv )
        throw ( DAVException );

    void
    POST( const rtl::OUString & rContentType,
      const rtl::OUString & rReferer,
      const com::sun::star::uno::Reference<
          com::sun::star::io::XInputStream > & rInputStream,
      com::sun::star::uno::Reference<
          com::sun::star::io::XOutputStream > & rOutputStream,
      const com::sun::star::uno::Reference<
          com::sun::star::ucb::XCommandEnvironment >& xEnv )
        throw ( DAVException );

    void
    MKCOL( const com::sun::star::uno::Reference<
           com::sun::star::ucb::XCommandEnvironment > & xEnv )
    throw( DAVException );

    void
    COPY( const ::rtl::OUString & rSourcePath,
      const ::rtl::OUString & rDestinationURI,
      sal_Bool bOverwrite,
      const com::sun::star::uno::Reference<
          com::sun::star::ucb::XCommandEnvironment > & xEnv )
    throw( DAVException );

    void
    MOVE( const ::rtl::OUString & rSourcePath,
      const ::rtl::OUString & rDestinationURI,
      sal_Bool bOverwrite,
      const com::sun::star::uno::Reference<
          com::sun::star::ucb::XCommandEnvironment > & xEnv )
    throw( DAVException );

    void
    DESTROY( const com::sun::star::uno::Reference<
              com::sun::star::ucb::XCommandEnvironment > & xEnv )
    throw( DAVException );

    void
    LOCK( const com::sun::star::ucb::Lock & rLock,
      const com::sun::star::uno::Reference<
          com::sun::star::ucb::XCommandEnvironment > & xEnv )
    throw( DAVException );

    void
    UNLOCK( const com::sun::star::ucb::Lock & rLock,
        const com::sun::star::uno::Reference<
            com::sun::star::ucb::XCommandEnvironment > & xEnv )
    throw( DAVException );

    // helper
    static void getUserRequestHeaders(
    const com::sun::star::uno::Reference<
        com::sun::star::ucb::XCommandEnvironment > & xEnv,
    const rtl::OUString & rURI,
    const rtl::OUString & rMethod,
    DAVRequestHeaders & rRequestHeaders );

private:
    const rtl::OUString & getRequestURI() const;
    sal_Bool detectRedirectCycle( const rtl::OUString& rRedirectURL );
    sal_Bool handleException( DAVException & e )
        throw ( DAVException );
    void initialize()
        throw ( DAVException );
};

} // namespace webdav_ucp

#endif // _DAVRESOURCEACCESS_HXX_
<|endoftext|>


<commit_before>//===-- sanitizer_thread_registry_test.cc ---------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file is a part of shared sanitizer runtime.
//
//===----------------------------------------------------------------------===//
#include "sanitizer_common/sanitizer_thread_registry.h"

#include "sanitizer_pthread_wrappers.h"

#include "gtest/gtest.h"

#include <vector>

namespace __sanitizer {

static BlockingMutex tctx_allocator_lock(LINKER_INITIALIZED);
static LowLevelAllocator tctx_allocator;

template<typename TCTX>
static ThreadContextBase *GetThreadContext(u32 tid) {
  BlockingMutexLock l(&tctx_allocator_lock);
  return new(tctx_allocator) TCTX(tid);
}

static const u32 kMaxRegistryThreads = 1000;
static const u32 kRegistryQuarantine = 2;

static void CheckThreadQuantity(ThreadRegistry *registry, uptr exp_total,
                                uptr exp_running, uptr exp_alive) {
  uptr total, running, alive;
  registry->GetNumberOfThreads(&total, &running, &alive);
  EXPECT_EQ(exp_total, total);
  EXPECT_EQ(exp_running, running);
  EXPECT_EQ(exp_alive, alive);
}

static bool is_detached(u32 tid) {
  return (tid % 2 == 0);
}

static uptr get_uid(u32 tid) {
  return tid * 2;
}

static bool HasName(ThreadContextBase *tctx, void *arg) {
  char *name = (char*)arg;
  return (0 == internal_strcmp(tctx->name, name));
}

static bool HasUid(ThreadContextBase *tctx, void *arg) {
  uptr uid = (uptr)arg;
  return (tctx->user_id == uid);
}

static void MarkUidAsPresent(ThreadContextBase *tctx, void *arg) {
  bool *arr = (bool*)arg;
  arr[tctx->tid] = true;
}

static void TestRegistry(ThreadRegistry *registry, bool has_quarantine) {
  // Create and start a main thread.
  EXPECT_EQ(0U, registry->CreateThread(get_uid(0), true, -1, 0));
  registry->StartThread(0, 0, 0);
  // Create a bunch of threads.
  for (u32 i = 1; i <= 10; i++) {
    EXPECT_EQ(i, registry->CreateThread(get_uid(i), is_detached(i), 0, 0));
  }
  CheckThreadQuantity(registry, 11, 1, 11);
  // Start some of them.
  for (u32 i = 1; i <= 5; i++) {
    registry->StartThread(i, 0, 0);
  }
  CheckThreadQuantity(registry, 11, 6, 11);
  // Finish, create and start more threads.
  for (u32 i = 1; i <= 5; i++) {
    registry->FinishThread(i);
    if (!is_detached(i))
      registry->JoinThread(i, 0);
  }
  for (u32 i = 6; i <= 10; i++) {
    registry->StartThread(i, 0, 0);
  }
  std::vector<u32> new_tids;
  for (u32 i = 11; i <= 15; i++) {
    new_tids.push_back(
        registry->CreateThread(get_uid(i), is_detached(i), 0, 0));
  }
  ASSERT_LE(kRegistryQuarantine, 5U);
  u32 exp_total = 16 - (has_quarantine ? 5 - kRegistryQuarantine  : 0);
  CheckThreadQuantity(registry, exp_total, 6, 11);
  // Test SetThreadName and FindThread.
  registry->SetThreadName(6, "six");
  registry->SetThreadName(7, "seven");
  EXPECT_EQ(7U, registry->FindThread(HasName, (void*)"seven"));
  EXPECT_EQ(ThreadRegistry::kUnknownTid,
            registry->FindThread(HasName, (void*)"none"));
  EXPECT_EQ(0U, registry->FindThread(HasUid, (void*)get_uid(0)));
  EXPECT_EQ(10U, registry->FindThread(HasUid, (void*)get_uid(10)));
  EXPECT_EQ(ThreadRegistry::kUnknownTid,
            registry->FindThread(HasUid, (void*)0x1234));
  // Detach and finish and join remaining threads.
  for (u32 i = 6; i <= 10; i++) {
    registry->DetachThread(i, 0);
    registry->FinishThread(i);
  }
  for (u32 i = 0; i < new_tids.size(); i++) {
    u32 tid = new_tids[i];
    registry->StartThread(tid, 0, 0);
    registry->DetachThread(tid, 0);
    registry->FinishThread(tid);
  }
  CheckThreadQuantity(registry, exp_total, 1, 1);
  // Test methods that require the caller to hold a ThreadRegistryLock.
  bool has_tid[16];
  internal_memset(&has_tid[0], 0, sizeof(has_tid));
  {
    ThreadRegistryLock l(registry);
    registry->RunCallbackForEachThreadLocked(MarkUidAsPresent, &has_tid[0]);
  }
  for (u32 i = 0; i < exp_total; i++) {
    EXPECT_TRUE(has_tid[i]);
  }
  {
    ThreadRegistryLock l(registry);
    registry->CheckLocked();
    ThreadContextBase *main_thread = registry->GetThreadLocked(0);
    EXPECT_EQ(main_thread, registry->FindThreadContextLocked(
        HasUid, (void*)get_uid(0)));
  }
  EXPECT_EQ(11U, registry->GetMaxAliveThreads());
}

TEST(SanitizerCommon, ThreadRegistryTest) {
  ThreadRegistry quarantine_registry(GetThreadContext<ThreadContextBase>,
                                     kMaxRegistryThreads,
                                     kRegistryQuarantine);
  TestRegistry(&quarantine_registry, true);

  ThreadRegistry no_quarantine_registry(GetThreadContext<ThreadContextBase>,
                                        kMaxRegistryThreads,
                                        kMaxRegistryThreads);
  TestRegistry(&no_quarantine_registry, false);
}

static const int kThreadsPerShard = 20;
static const int kNumShards = 25;

static int num_created[kNumShards + 1];
static int num_started[kNumShards + 1];
static int num_joined[kNumShards + 1];

namespace {

struct RunThreadArgs {
  ThreadRegistry *registry;
  uptr shard;  // started from 1.
};

class TestThreadContext : public ThreadContextBase {
 public:
  explicit TestThreadContext(int tid) : ThreadContextBase(tid) {}
  void OnJoined(void *arg) {
    uptr shard = (uptr)arg;
    num_joined[shard]++;
  }
  void OnStarted(void *arg) {
    uptr shard = (uptr)arg;
    num_started[shard]++;
  }
  void OnCreated(void *arg) {
    uptr shard = (uptr)arg;
    num_created[shard]++;
  }
};

}  // namespace

void *RunThread(void *arg) {
  RunThreadArgs *args = static_cast<RunThreadArgs*>(arg);
  std::vector<int> tids;
  for (int i = 0; i < kThreadsPerShard; i++)
    tids.push_back(
        args->registry->CreateThread(0, false, 0, (void*)args->shard));
  for (int i = 0; i < kThreadsPerShard; i++)
    args->registry->StartThread(tids[i], 0, (void*)args->shard);
  for (int i = 0; i < kThreadsPerShard; i++)
    args->registry->FinishThread(tids[i]);
  for (int i = 0; i < kThreadsPerShard; i++)
    args->registry->JoinThread(tids[i], (void*)args->shard);
  return 0;
}

static void ThreadedTestRegistry(ThreadRegistry *registry) {
  // Create and start a main thread.
  EXPECT_EQ(0U, registry->CreateThread(0, true, -1, 0));
  registry->StartThread(0, 0, 0);
  pthread_t threads[kNumShards];
  RunThreadArgs args[kNumShards];
  for (int i = 0; i < kNumShards; i++) {
    args[i].registry = registry;
    args[i].shard = i + 1;
    PTHREAD_CREATE(&threads[i], 0, RunThread, &args[i]);
  }
  for (int i = 0; i < kNumShards; i++) {
    PTHREAD_JOIN(threads[i], 0);
  }
  // Check that each thread created/started/joined correct amount
  // of "threads" in thread_registry.
  EXPECT_EQ(1, num_created[0]);
  EXPECT_EQ(1, num_started[0]);
  EXPECT_EQ(0, num_joined[0]);
  for (int i = 1; i <= kNumShards; i++) {
    EXPECT_EQ(kThreadsPerShard, num_created[i]);
    EXPECT_EQ(kThreadsPerShard, num_started[i]);
    EXPECT_EQ(kThreadsPerShard, num_joined[i]);
  }
}

TEST(SanitizerCommon, ThreadRegistryThreadedTest) {
  ThreadRegistry registry(GetThreadContext<TestThreadContext>,
                          kThreadsPerShard * kNumShards + 1, 10);
  ThreadedTestRegistry(&registry);
}

}  // namespace __sanitizer
<commit_msg>[compiler-rt] Reset global variables in ThreadRegistryThreadedTest<commit_after>//===-- sanitizer_thread_registry_test.cc ---------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file is a part of shared sanitizer runtime.
//
//===----------------------------------------------------------------------===//
#include "sanitizer_common/sanitizer_thread_registry.h"

#include "sanitizer_pthread_wrappers.h"

#include "gtest/gtest.h"

#include <vector>

namespace __sanitizer {

static BlockingMutex tctx_allocator_lock(LINKER_INITIALIZED);
static LowLevelAllocator tctx_allocator;

template<typename TCTX>
static ThreadContextBase *GetThreadContext(u32 tid) {
  BlockingMutexLock l(&tctx_allocator_lock);
  return new(tctx_allocator) TCTX(tid);
}

static const u32 kMaxRegistryThreads = 1000;
static const u32 kRegistryQuarantine = 2;

static void CheckThreadQuantity(ThreadRegistry *registry, uptr exp_total,
                                uptr exp_running, uptr exp_alive) {
  uptr total, running, alive;
  registry->GetNumberOfThreads(&total, &running, &alive);
  EXPECT_EQ(exp_total, total);
  EXPECT_EQ(exp_running, running);
  EXPECT_EQ(exp_alive, alive);
}

static bool is_detached(u32 tid) {
  return (tid % 2 == 0);
}

static uptr get_uid(u32 tid) {
  return tid * 2;
}

static bool HasName(ThreadContextBase *tctx, void *arg) {
  char *name = (char*)arg;
  return (0 == internal_strcmp(tctx->name, name));
}

static bool HasUid(ThreadContextBase *tctx, void *arg) {
  uptr uid = (uptr)arg;
  return (tctx->user_id == uid);
}

static void MarkUidAsPresent(ThreadContextBase *tctx, void *arg) {
  bool *arr = (bool*)arg;
  arr[tctx->tid] = true;
}

static void TestRegistry(ThreadRegistry *registry, bool has_quarantine) {
  // Create and start a main thread.
  EXPECT_EQ(0U, registry->CreateThread(get_uid(0), true, -1, 0));
  registry->StartThread(0, 0, 0);
  // Create a bunch of threads.
  for (u32 i = 1; i <= 10; i++) {
    EXPECT_EQ(i, registry->CreateThread(get_uid(i), is_detached(i), 0, 0));
  }
  CheckThreadQuantity(registry, 11, 1, 11);
  // Start some of them.
  for (u32 i = 1; i <= 5; i++) {
    registry->StartThread(i, 0, 0);
  }
  CheckThreadQuantity(registry, 11, 6, 11);
  // Finish, create and start more threads.
  for (u32 i = 1; i <= 5; i++) {
    registry->FinishThread(i);
    if (!is_detached(i))
      registry->JoinThread(i, 0);
  }
  for (u32 i = 6; i <= 10; i++) {
    registry->StartThread(i, 0, 0);
  }
  std::vector<u32> new_tids;
  for (u32 i = 11; i <= 15; i++) {
    new_tids.push_back(
        registry->CreateThread(get_uid(i), is_detached(i), 0, 0));
  }
  ASSERT_LE(kRegistryQuarantine, 5U);
  u32 exp_total = 16 - (has_quarantine ? 5 - kRegistryQuarantine  : 0);
  CheckThreadQuantity(registry, exp_total, 6, 11);
  // Test SetThreadName and FindThread.
  registry->SetThreadName(6, "six");
  registry->SetThreadName(7, "seven");
  EXPECT_EQ(7U, registry->FindThread(HasName, (void*)"seven"));
  EXPECT_EQ(ThreadRegistry::kUnknownTid,
            registry->FindThread(HasName, (void*)"none"));
  EXPECT_EQ(0U, registry->FindThread(HasUid, (void*)get_uid(0)));
  EXPECT_EQ(10U, registry->FindThread(HasUid, (void*)get_uid(10)));
  EXPECT_EQ(ThreadRegistry::kUnknownTid,
            registry->FindThread(HasUid, (void*)0x1234));
  // Detach and finish and join remaining threads.
  for (u32 i = 6; i <= 10; i++) {
    registry->DetachThread(i, 0);
    registry->FinishThread(i);
  }
  for (u32 i = 0; i < new_tids.size(); i++) {
    u32 tid = new_tids[i];
    registry->StartThread(tid, 0, 0);
    registry->DetachThread(tid, 0);
    registry->FinishThread(tid);
  }
  CheckThreadQuantity(registry, exp_total, 1, 1);
  // Test methods that require the caller to hold a ThreadRegistryLock.
  bool has_tid[16];
  internal_memset(&has_tid[0], 0, sizeof(has_tid));
  {
    ThreadRegistryLock l(registry);
    registry->RunCallbackForEachThreadLocked(MarkUidAsPresent, &has_tid[0]);
  }
  for (u32 i = 0; i < exp_total; i++) {
    EXPECT_TRUE(has_tid[i]);
  }
  {
    ThreadRegistryLock l(registry);
    registry->CheckLocked();
    ThreadContextBase *main_thread = registry->GetThreadLocked(0);
    EXPECT_EQ(main_thread, registry->FindThreadContextLocked(
        HasUid, (void*)get_uid(0)));
  }
  EXPECT_EQ(11U, registry->GetMaxAliveThreads());
}

TEST(SanitizerCommon, ThreadRegistryTest) {
  ThreadRegistry quarantine_registry(GetThreadContext<ThreadContextBase>,
                                     kMaxRegistryThreads,
                                     kRegistryQuarantine);
  TestRegistry(&quarantine_registry, true);

  ThreadRegistry no_quarantine_registry(GetThreadContext<ThreadContextBase>,
                                        kMaxRegistryThreads,
                                        kMaxRegistryThreads);
  TestRegistry(&no_quarantine_registry, false);
}

static const int kThreadsPerShard = 20;
static const int kNumShards = 25;

static int num_created[kNumShards + 1];
static int num_started[kNumShards + 1];
static int num_joined[kNumShards + 1];

namespace {

struct RunThreadArgs {
  ThreadRegistry *registry;
  uptr shard;  // started from 1.
};

class TestThreadContext : public ThreadContextBase {
 public:
  explicit TestThreadContext(int tid) : ThreadContextBase(tid) {}
  void OnJoined(void *arg) {
    uptr shard = (uptr)arg;
    num_joined[shard]++;
  }
  void OnStarted(void *arg) {
    uptr shard = (uptr)arg;
    num_started[shard]++;
  }
  void OnCreated(void *arg) {
    uptr shard = (uptr)arg;
    num_created[shard]++;
  }
};

}  // namespace

void *RunThread(void *arg) {
  RunThreadArgs *args = static_cast<RunThreadArgs*>(arg);
  std::vector<int> tids;
  for (int i = 0; i < kThreadsPerShard; i++)
    tids.push_back(
        args->registry->CreateThread(0, false, 0, (void*)args->shard));
  for (int i = 0; i < kThreadsPerShard; i++)
    args->registry->StartThread(tids[i], 0, (void*)args->shard);
  for (int i = 0; i < kThreadsPerShard; i++)
    args->registry->FinishThread(tids[i]);
  for (int i = 0; i < kThreadsPerShard; i++)
    args->registry->JoinThread(tids[i], (void*)args->shard);
  return 0;
}

static void ThreadedTestRegistry(ThreadRegistry *registry) {
  // Create and start a main thread.
  EXPECT_EQ(0U, registry->CreateThread(0, true, -1, 0));
  registry->StartThread(0, 0, 0);
  pthread_t threads[kNumShards];
  RunThreadArgs args[kNumShards];
  for (int i = 0; i < kNumShards; i++) {
    args[i].registry = registry;
    args[i].shard = i + 1;
    PTHREAD_CREATE(&threads[i], 0, RunThread, &args[i]);
  }
  for (int i = 0; i < kNumShards; i++) {
    PTHREAD_JOIN(threads[i], 0);
  }
  // Check that each thread created/started/joined correct amount
  // of "threads" in thread_registry.
  EXPECT_EQ(1, num_created[0]);
  EXPECT_EQ(1, num_started[0]);
  EXPECT_EQ(0, num_joined[0]);
  for (int i = 1; i <= kNumShards; i++) {
    EXPECT_EQ(kThreadsPerShard, num_created[i]);
    EXPECT_EQ(kThreadsPerShard, num_started[i]);
    EXPECT_EQ(kThreadsPerShard, num_joined[i]);
  }
}

TEST(SanitizerCommon, ThreadRegistryThreadedTest) {
  memset(&num_created, 0, sizeof(num_created));
  memset(&num_started, 0, sizeof(num_created));
  memset(&num_joined, 0, sizeof(num_created));

  ThreadRegistry registry(GetThreadContext<TestThreadContext>,
                          kThreadsPerShard * kNumShards + 1, 10);
  ThreadedTestRegistry(&registry);
}

}  // namespace __sanitizer
<|endoftext|>


<commit_before>#include <stdarg.h>
#include <stdio.h>

#ifndef va_copy
#  ifdef __va_copy
#    define va_copy __va_copy
#  else
#    define va_copy(dst, src) memcpy(&dst, &src, sizeof(va_list))
#  endif
#endif

#include "string_buf.hpp"

  // reserve space for at least s+1 characters
  void StringBuf::reserve_i(size_t s)
  {
    size_t old_size = end_ - begin_;
    size_t new_size = (storage_end_ - begin_) * 3 / 2;
    if (new_size < 60) new_size = 60;
    if (new_size < s + 1) new_size = s + 1;
    if (old_size == 0) {
      if (d) GC_FREE(d);
      d = (StringObj *)GC_MALLOC_ATOMIC(sizeof(StringObj) + new_size);
    } else {
      StringObj * d2 = (StringObj *)GC_MALLOC_ATOMIC(sizeof(StringObj) + new_size);
      memcpy(d2->str, d->str, old_size);
      GC_FREE(d);
      d = d2;
    }
    begin_ = d->str;
    d->size = 0;
    end_ = begin_ + old_size;
    storage_end_ = begin_ + new_size;
  }

  int StringBuf::vprintf(const char * format, va_list ap0)
  {
    reserve(size() + 64);
    int res = 0;
    va_list ap;
  loop: {
      int avail = storage_end_ - end_ - 1;
      if (res < 0 && avail > 1024*1024)
        return -1; // to avoid an infinite loop in case a neg result
                   // really means an error and not just "not enough
                   // space"
      va_copy(ap,ap0);
      res = vsnprintf(end_, avail, format, ap);
      va_end(ap);
      if (res < 0) {
        reserve_i(); goto loop;
      } else if (res > avail) {
        reserve_i(size() + res); goto loop;
      }
    }
    end_ += res;
    return res;
  }

  bool StringIStream::append_line(StringBuf & str, char d)
  {
    if (in_str[0] == '\0') return false;
    const char * end = in_str;
    while (*end != d && *end != '\0') ++end;
    str.append(in_str, end - in_str);
    in_str = end;
    if (*in_str == d) ++in_str;
    return true;
  }

  bool StringIStream::read(void * data, unsigned int size)
  {
    char * str = static_cast<char *>(data);
    while (*in_str != '\0' && size != 0) {
      *str = *in_str;
      ++in_str;
      ++str;
      ++size;
    }
    return size == 0;
  }

<commit_msg>Bug fix.<commit_after>#include <stdarg.h>
#include <stdio.h>

#ifndef va_copy
#  ifdef __va_copy
#    define va_copy __va_copy
#  else
#    define va_copy(dst, src) memcpy(&dst, &src, sizeof(va_list))
#  endif
#endif

#include "string_buf.hpp"

  // reserve space for at least s+1 characters
  void StringBuf::reserve_i(size_t s)
  {
    size_t old_size = end_ - begin_;
    size_t new_size = (storage_end_ - begin_) * 3 / 2;
    if (new_size < 60) new_size = 60;
    if (new_size < s + 1) new_size = s + 1;
    if (old_size == 0) {
      if (d) GC_FREE(d);
      d = (StringObj *)GC_MALLOC_ATOMIC(sizeof(StringObj) + new_size);
    } else {
      StringObj * d2 = (StringObj *)GC_MALLOC_ATOMIC(sizeof(StringObj) + new_size);
      memcpy(d2->str, d->str, old_size);
      GC_FREE(d);
      d = d2;
    }
    begin_ = d->str;
    d->size = 0;
    end_ = begin_ + old_size;
    storage_end_ = begin_ + new_size;
  }

  int StringBuf::vprintf(const char * format, va_list ap0)
  {
    reserve(size() + 64);
    int res = 0;
    va_list ap;
  loop: {
      int avail = storage_end_ - end_ - 1;
      if (res < 0 && avail > 1024*1024)
        return -1; // to avoid an infinite loop in case a neg result
                   // really means an error and not just "not enough
                   // space"
      va_copy(ap,ap0);
      res = vsnprintf(end_, avail + 1, format, ap);
      va_end(ap);
      if (res < 0) {
        reserve_i(); goto loop;
      } else if (res > avail) {
        reserve_i(size() + res); goto loop;
      }
    }
    end_ += res;
    return res;
  }

  bool StringIStream::append_line(StringBuf & str, char d)
  {
    if (in_str[0] == '\0') return false;
    const char * end = in_str;
    while (*end != d && *end != '\0') ++end;
    str.append(in_str, end - in_str);
    in_str = end;
    if (*in_str == d) ++in_str;
    return true;
  }

  bool StringIStream::read(void * data, unsigned int size)
  {
    char * str = static_cast<char *>(data);
    while (*in_str != '\0' && size != 0) {
      *str = *in_str;
      ++in_str;
      ++str;
      ++size;
    }
    return size == 0;
  }

<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you 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 .
 */

#ifndef _MACSPELLIMP_H_
#define _MACSPELLIMP_H_

#include <cppuhelper/implbase1.hxx>
#include <cppuhelper/implbase6.hxx>

#ifdef MACOSX
#include <premac.h>
#include <Carbon/Carbon.h>
#import <Cocoa/Cocoa.h>
#include <postmac.h>
#endif
#include <com/sun/star/lang/XComponent.hpp>
#include <com/sun/star/lang/XInitialization.hpp>
#include <com/sun/star/lang/XServiceDisplayName.hpp>
#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/beans/PropertyValues.hpp>
#include <com/sun/star/lang/XServiceInfo.hpp>
#include <com/sun/star/linguistic2/XSpellChecker.hpp>
#include <com/sun/star/linguistic2/XSearchableDictionaryList.hpp>
#include <com/sun/star/linguistic2/XLinguServiceEventBroadcaster.hpp>

#include <linguistic/misc.hxx>
#include <linguistic/lngprophelp.hxx>

#include <lingutil.hxx>

using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::beans;
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::linguistic2;

class MacSpellChecker :
    public cppu::WeakImplHelper6
    <
        XSpellChecker,
        XLinguServiceEventBroadcaster,
        XInitialization,
        XComponent,
        XServiceInfo,
        XServiceDisplayName
    >
{
    Sequence< Locale >      aSuppLocales;
    rtl_TextEncoding *      aDEncs;
    Locale *                aDLocs;
    OUString *              aDNames;
    sal_Int32               numdict;
    NSSpellChecker *        macSpell;
    int                     macTag;   // unique tag for this doc

    ::cppu::OInterfaceContainerHelper       aEvtListeners;
    Reference< XPropertyChangeListener >    xPropHelper;
    linguistic::PropertyHelper_Spell *      pPropHelper;
    bool                                    bDisposing;

    // disallow copy-constructor and assignment-operator for now
    MacSpellChecker(const MacSpellChecker &);
    MacSpellChecker & operator = (const MacSpellChecker &);

    linguistic::PropertyHelper_Spell &  GetPropHelper_Impl();
    linguistic::PropertyHelper_Spell &  GetPropHelper()
    {
        return pPropHelper ? *pPropHelper : GetPropHelper_Impl();
    }

    sal_Int16   GetSpellFailure( const OUString &rWord, const Locale &rLocale );
    Reference< XSpellAlternatives > GetProposals( const OUString &rWord, const Locale &rLocale );

public:
    MacSpellChecker();
    virtual ~MacSpellChecker();

    // XSupportedLocales (for XSpellChecker)
    virtual Sequence< Locale > SAL_CALL getLocales() throw(RuntimeException);
    virtual sal_Bool SAL_CALL hasLocale( const Locale& rLocale ) throw(RuntimeException);

    // XSpellChecker
    virtual sal_Bool SAL_CALL isValid( const OUString& rWord, const Locale& rLocale, const PropertyValues& rProperties ) throw(IllegalArgumentException, RuntimeException);
    virtual Reference< XSpellAlternatives > SAL_CALL spell( const OUString& rWord, const Locale& rLocale, const PropertyValues& rProperties ) throw(IllegalArgumentException, RuntimeException);

    // XLinguServiceEventBroadcaster
    virtual sal_Bool SAL_CALL addLinguServiceEventListener( const Reference< XLinguServiceEventListener >& rxLstnr ) throw(RuntimeException);
    virtual sal_Bool SAL_CALL removeLinguServiceEventListener( const Reference< XLinguServiceEventListener >& rxLstnr ) throw(RuntimeException);

    // XServiceDisplayName
    virtual OUString SAL_CALL getServiceDisplayName( const Locale& rLocale ) throw(RuntimeException);

    // XInitialization
    virtual void SAL_CALL initialize( const Sequence< Any >& rArguments ) throw(Exception, RuntimeException);

    // XComponent
    virtual void SAL_CALL dispose() throw(RuntimeException);
    virtual void SAL_CALL addEventListener( const Reference< XEventListener >& rxListener ) throw(RuntimeException);
    virtual void SAL_CALL removeEventListener( const Reference< XEventListener >& rxListener ) throw(RuntimeException);

    // XServiceInfo
    virtual OUString SAL_CALL getImplementationName() throw(RuntimeException);
    virtual sal_Bool SAL_CALL supportsService( const OUString& rServiceName ) throw(RuntimeException);
    virtual Sequence< OUString > SAL_CALL getSupportedServiceNames() throw(RuntimeException);

    static inline OUString  getImplementationName_Static() throw();
    static Sequence< OUString > getSupportedServiceNames_Static() throw();
};

inline OUString MacSpellChecker::getImplementationName_Static() throw()
{
    return OUString( "org.openoffice.lingu.MacOSXSpellChecker" );
}

#endif

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>loplugin:saloverride<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you 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 .
 */

#ifndef _MACSPELLIMP_H_
#define _MACSPELLIMP_H_

#include <cppuhelper/implbase1.hxx>
#include <cppuhelper/implbase6.hxx>

#ifdef MACOSX
#include <premac.h>
#include <Carbon/Carbon.h>
#import <Cocoa/Cocoa.h>
#include <postmac.h>
#endif
#include <com/sun/star/lang/XComponent.hpp>
#include <com/sun/star/lang/XInitialization.hpp>
#include <com/sun/star/lang/XServiceDisplayName.hpp>
#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/beans/PropertyValues.hpp>
#include <com/sun/star/lang/XServiceInfo.hpp>
#include <com/sun/star/linguistic2/XSpellChecker.hpp>
#include <com/sun/star/linguistic2/XSearchableDictionaryList.hpp>
#include <com/sun/star/linguistic2/XLinguServiceEventBroadcaster.hpp>

#include <linguistic/misc.hxx>
#include <linguistic/lngprophelp.hxx>

#include <lingutil.hxx>

using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::beans;
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::linguistic2;

class MacSpellChecker :
    public cppu::WeakImplHelper6
    <
        XSpellChecker,
        XLinguServiceEventBroadcaster,
        XInitialization,
        XComponent,
        XServiceInfo,
        XServiceDisplayName
    >
{
    Sequence< Locale >      aSuppLocales;
    rtl_TextEncoding *      aDEncs;
    Locale *                aDLocs;
    OUString *              aDNames;
    sal_Int32               numdict;
    NSSpellChecker *        macSpell;
    int                     macTag;   // unique tag for this doc

    ::cppu::OInterfaceContainerHelper       aEvtListeners;
    Reference< XPropertyChangeListener >    xPropHelper;
    linguistic::PropertyHelper_Spell *      pPropHelper;
    bool                                    bDisposing;

    // disallow copy-constructor and assignment-operator for now
    MacSpellChecker(const MacSpellChecker &);
    MacSpellChecker & operator = (const MacSpellChecker &);

    linguistic::PropertyHelper_Spell &  GetPropHelper_Impl();
    linguistic::PropertyHelper_Spell &  GetPropHelper()
    {
        return pPropHelper ? *pPropHelper : GetPropHelper_Impl();
    }

    sal_Int16   GetSpellFailure( const OUString &rWord, const Locale &rLocale );
    Reference< XSpellAlternatives > GetProposals( const OUString &rWord, const Locale &rLocale );

public:
    MacSpellChecker();
    virtual ~MacSpellChecker();

    // XSupportedLocales (for XSpellChecker)
    virtual Sequence< Locale > SAL_CALL getLocales() throw(RuntimeException) SAL_OVERRIDE;
    virtual sal_Bool SAL_CALL hasLocale( const Locale& rLocale ) throw(RuntimeException) SAL_OVERRIDE;

    // XSpellChecker
    virtual sal_Bool SAL_CALL isValid( const OUString& rWord, const Locale& rLocale, const PropertyValues& rProperties ) throw(IllegalArgumentException, RuntimeException) SAL_OVERRIDE;
    virtual Reference< XSpellAlternatives > SAL_CALL spell( const OUString& rWord, const Locale& rLocale, const PropertyValues& rProperties ) throw(IllegalArgumentException, RuntimeException) SAL_OVERRIDE;

    // XLinguServiceEventBroadcaster
    virtual sal_Bool SAL_CALL addLinguServiceEventListener( const Reference< XLinguServiceEventListener >& rxLstnr ) throw(RuntimeException) SAL_OVERRIDE;
    virtual sal_Bool SAL_CALL removeLinguServiceEventListener( const Reference< XLinguServiceEventListener >& rxLstnr ) throw(RuntimeException) SAL_OVERRIDE;

    // XServiceDisplayName
    virtual OUString SAL_CALL getServiceDisplayName( const Locale& rLocale ) throw(RuntimeException) SAL_OVERRIDE;

    // XInitialization
    virtual void SAL_CALL initialize( const Sequence< Any >& rArguments ) throw(Exception, RuntimeException) SAL_OVERRIDE;

    // XComponent
    virtual void SAL_CALL dispose() throw(RuntimeException) SAL_OVERRIDE;
    virtual void SAL_CALL addEventListener( const Reference< XEventListener >& rxListener ) throw(RuntimeException) SAL_OVERRIDE;
    virtual void SAL_CALL removeEventListener( const Reference< XEventListener >& rxListener ) throw(RuntimeException) SAL_OVERRIDE;

    // XServiceInfo
    virtual OUString SAL_CALL getImplementationName() throw(RuntimeException) SAL_OVERRIDE;
    virtual sal_Bool SAL_CALL supportsService( const OUString& rServiceName ) throw(RuntimeException) SAL_OVERRIDE;
    virtual Sequence< OUString > SAL_CALL getSupportedServiceNames() throw(RuntimeException) SAL_OVERRIDE;

    static inline OUString  getImplementationName_Static() throw();
    static Sequence< OUString > getSupportedServiceNames_Static() throw();
};

inline OUString MacSpellChecker::getImplementationName_Static() throw()
{
    return OUString( "org.openoffice.lingu.MacOSXSpellChecker" );
}

#endif

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<|endoftext|>


<commit_before>// -*- Mode:C++ -*-

/**************************************************************************************************/
/*                                                                                */
/* Copyright (C) 2016 University of Hull                                                          */
/*                                                                                */
/**************************************************************************************************/
/*                                                                                */
/*  module     :  hugh/render/software/test/pipeline/fixed.cpp                                    */
/*  project    :                                                                                */
/*  description:                                                                                */
/*                                                                                */
/**************************************************************************************************/

// includes, system

#include <memory>  // std::unique_ptr<>
#include <sstream> // std::ostringstream

// includes, project

#include <hugh/render/software/buffer/color.hpp>
#include <hugh/render/software/buffer/depth.hpp>
#include <hugh/render/software/pipeline/fixed.hpp>
#include <hugh/render/software/primitives.hpp>
#include <hugh/render/software/rasterizer/simple.hpp>

#define HUGH_USE_TRACE
#undef HUGH_USE_TRACE
#include <hugh/support/trace.hpp>

// internal unnamed namespace

namespace {

  // types, internal (class, enum, struct, union, typedef)

  // variables, internal

  // functions, internal

} // namespace {

#define BOOST_TEST_MAIN
#include <boost/test/unit_test.hpp>

BOOST_AUTO_TEST_CASE(test_hugh_render_software_pipeline_fixed_ctor)
{
  using namespace hugh::render::software;

  std::unique_ptr<pipeline::base> const p(new pipeline::fixed);

  BOOST_CHECK(nullptr != p);
}

BOOST_AUTO_TEST_CASE(test_hugh_render_software_pipeline_fixed_process)
{
  TRACE("test_hugh_render_software_pipeline_fixed_process");

  using namespace hugh::render::software;
  using viewport = hugh::scene::object::camera::viewport;

  viewport const  vp(0, 0, 80, 60, 0, 1);
  //viewport const  vp(0, 0, 160, 120, 0, 1);
  //viewport const  vp(0, 0, 320, 240, 0, 1);
  //viewport const  vp(0, 0, 640, 480, 0, 1);
  //viewport const  vp(0, 0, 1600, 1200, 0, 1);
  pipeline::fixed ppl;

  ppl.rasterizer  = new rasterizer::simple(vp);
  ppl.colorbuffer = new buffer::color(vp);
  ppl.depthbuffer = new buffer::depth(vp);

  {
    using point_list  = primitive::point_list;
    using index_list  = point_list::index_list_type;
    using vertex_list = point_list::vertex_list_type;

    vertex_list    vl;
    unsigned const stride((vp.width-vp.x)/std::min(vp.width-vp.x, float(200)));

    for (unsigned x(vp.x); x < (vp.x + vp.width); x += stride) {
      for (unsigned y(vp.y); y < (vp.y + vp.height); y += stride) {
        vl.push_back(vertex(glm::vec3(x, y,  1.5)));  // > vp.far  -> false
        vl.push_back(vertex(glm::vec3(x, y,  0.75))); // < current -> true
        vl.push_back(vertex(glm::vec3(x, y,  0.25))); // < current -> true
        vl.push_back(vertex(glm::vec3(x, y,  0.5)));  // > current -> false
        vl.push_back(vertex(glm::vec3(x, y, -0.25))); // < vp.near -> false
      }
    }

    {
      point_list const p(vl);

      ppl.process(p);
    }

    auto const lstats(*ppl.stats);

    {
      index_list il(vl.size());

      std::iota(il.begin(), il.end(), 0);

      point_list const p(vl, il);

      ppl.process(p);
    }

    auto const ilstats(*ppl.stats);

    BOOST_CHECK(ilstats.vertices.processed >  lstats.vertices.processed);
    BOOST_CHECK(ilstats.fragments.created  >  lstats.fragments.created);
    BOOST_CHECK(ilstats.fragments.updated  == lstats.fragments.updated);
  }

  (*ppl.depthbuffer)->clear();

  {
    using line_list   = primitive::line_list;
    using index_list  = line_list::index_list_type;
    using vertex_list = line_list::vertex_list_type;

    vertex_list    vl;
    unsigned const stride((vp.width-vp.x)/std::min(vp.width-vp.x, float(100)));

    for (unsigned x(vp.x); x < (vp.x + vp.width); x += stride) {
      for (unsigned y(vp.y); y < (vp.y + vp.height); y += stride) {
        vl.push_back(vertex(glm::vec3(       x,        y, 0.25)));
        vl.push_back(vertex(glm::vec3(x+stride, y+stride, 0.75)));
        vl.push_back(vertex(glm::vec3(x+stride, y+stride, 0.25)));
        vl.push_back(vertex(glm::vec3(       x,        y, 0.75)));
      }
    }

    {
      line_list const l(vl);

      ppl.process(l);
    }

    auto const lstats(*ppl.stats);

    {
      index_list il(vl.size());

      std::iota(il.begin(), il.end(), 0);

      line_list const l(vl, il);

      ppl.process(l);
    }

    auto const ilstats(*ppl.stats);

    BOOST_CHECK(ilstats.vertices.processed >  lstats.vertices.processed);
    BOOST_CHECK(ilstats.fragments.created  >  lstats.fragments.created);
    BOOST_CHECK(ilstats.fragments.updated  == lstats.fragments.updated);
  }

  (*ppl.depthbuffer)->clear();

  {
    using line_strip  = primitive::line_strip;
    using index_list  = line_strip::index_list_type;
    using vertex_list = line_strip::vertex_list_type;

    vertex_list    vl;
    unsigned const stride((vp.width-vp.x)/std::min(vp.width-vp.x, float(100)));

    for (unsigned x(vp.x); x < (vp.x + vp.width); x += stride) {
      for (unsigned y(vp.y); y < (vp.y + vp.height); y += stride) {
        vl.push_back(vertex(glm::vec3(       x,        y, 0.25)));
        vl.push_back(vertex(glm::vec3(x+stride, y+stride, 0.75)));
        vl.push_back(vertex(glm::vec3(       x,        y, 0.75)));
      }
    }

    {
      line_strip const l(vl);

      ppl.process(l);
    }

    auto const lstats(*ppl.stats);

    {
      index_list il(vl.size());

      std::iota(il.begin(), il.end(), 0);

      line_strip const l(vl, il);

      ppl.process(l);
    }

    auto const ilstats(*ppl.stats);

    BOOST_CHECK(ilstats.vertices.processed >  lstats.vertices.processed);
    BOOST_CHECK(ilstats.fragments.created  >  lstats.fragments.created);
    BOOST_CHECK(ilstats.fragments.updated  == lstats.fragments.updated);
  }

  (*ppl.depthbuffer)->clear();

  {
    using triangle_list = primitive::triangle_list;
    using index_list    = triangle_list::index_list_type;
    using vertex_list   = triangle_list::vertex_list_type;

    vertex_list    vl;
    unsigned const stride((vp.width-vp.x)/std::min(vp.width-vp.x, float(50)));

    for (unsigned x(vp.x); x < (vp.x + vp.width); x += stride) {
      for (unsigned y(vp.y); y < (vp.y + vp.height); y += stride) {
        // ccw -> fragments
        vl.push_back(vertex(glm::vec3(       x,        y, 0.25)));
        vl.push_back(vertex(glm::vec3(x+stride,        y, 0.35)));
        vl.push_back(vertex(glm::vec3(       x, y+stride, 0.45)));
        // cw -> !fragments
        vl.push_back(vertex(glm::vec3(       x,        y, 0.25)));
        vl.push_back(vertex(glm::vec3(       x, y+stride, 0.45)));
        vl.push_back(vertex(glm::vec3(x+stride,        y, 0.35)));
      }
    }

    {
      triangle_list const t(vl);

      ppl.process(t);
    }

    auto const lstats(*ppl.stats);

    {
      index_list il(vl.size());

      std::iota(il.begin(), il.end(), 0);

      triangle_list const l(vl, il);

      ppl.process(l);
    }

    auto const ilstats(*ppl.stats);

    BOOST_CHECK(ilstats.vertices.processed >  lstats.vertices.processed);
    BOOST_CHECK(ilstats.fragments.created  >  lstats.fragments.created);
    BOOST_CHECK(ilstats.fragments.updated  == lstats.fragments.updated);
  }

  (*ppl.depthbuffer)->clear();

  {
    using triangle_strip = primitive::triangle_strip;
    using index_list     = triangle_strip::index_list_type;
    using vertex_list    = triangle_strip::vertex_list_type;

    vertex_list    vl;
    unsigned const stride((vp.width-vp.x)/std::min(vp.width-vp.x, float(50)));

    for (unsigned x(vp.x); x < (vp.x + vp.width); x += stride) {
      for (unsigned y(vp.y); y < (vp.y + vp.height); y += stride) {
        // ccw -> fragments
        vl.push_back(vertex(glm::vec3(       x,        y, 0.25)));
        vl.push_back(vertex(glm::vec3(x+stride,        y, 0.35)));
        vl.push_back(vertex(glm::vec3(       x, y+stride, 0.45)));
        // cw -> !fragments
        vl.push_back(vertex(glm::vec3(       x,        y, 0.25)));
        vl.push_back(vertex(glm::vec3(       x, y+stride, 0.45)));
        vl.push_back(vertex(glm::vec3(x+stride,        y, 0.35)));
      }
    }

    {
      triangle_strip const t(vl);

      ppl.process(t);
    }

    auto const lstats(*ppl.stats);

    {
      index_list il(vl.size());

      std::iota(il.begin(), il.end(), 0);

      triangle_strip const l(vl, il);

      ppl.process(l);
    }

    auto const ilstats(*ppl.stats);

    BOOST_CHECK(ilstats.vertices.processed >  lstats.vertices.processed);
    BOOST_CHECK(ilstats.fragments.created  >  lstats.fragments.created);
    BOOST_CHECK(ilstats.fragments.updated  == lstats.fragments.updated);
  }
}
<commit_msg>update before rmove<commit_after>// -*- Mode:C++ -*-

/**************************************************************************************************/
/*                                                                                */
/* Copyright (C) 2016 University of Hull                                                          */
/*                                                                                */
/**************************************************************************************************/
/*                                                                                */
/*  module     :  hugh/render/software/test/pipeline_fixed.cpp                                    */
/*  project    :                                                                                */
/*  description:                                                                                */
/*                                                                                */
/**************************************************************************************************/

// includes, system

// #include <>

// includes, project

#include <hugh/render/software/buffer/color.hpp>
#include <hugh/render/software/buffer/depth.hpp>
#include <hugh/render/software/pipeline/fixed/base.hpp>
#include <hugh/render/software/rasterizer/simple.hpp>

#include <pipeline_fixed_shared.hpp>

#define HUGH_USE_TRACE
#undef HUGH_USE_TRACE
#include <hugh/support/trace.hpp>

// internal unnamed namespace

namespace {

  // types, internal (class, enum, struct, union, typedef)

  class fixed_generic : public hugh::render::software::pipeline::fixed::base {

  public:

    virtual glm::vec3 ndc_to_window(glm::vec3 const& a) const
    {
      return a;
    }

  };

  // variables, internal

  // functions, internal

} // namespace {

#define BOOST_TEST_MAIN
#include <boost/test/unit_test.hpp>

BOOST_AUTO_TEST_CASE(test_hugh_render_software_pipeline_fixed_process)
{
  TRACE("test_hugh_render_software_pipeline_fixed_process");

  using namespace hugh::render::software;
  using viewport = hugh::scene::object::camera::viewport;

  viewport const vp(0, 0, 80, 60, 0, 1);
  fixed_generic  ppl;

  ppl.rasterizer  = new rasterizer::simple(vp);
  ppl.colorbuffer = new buffer::color     (vp);
  ppl.depthbuffer = new buffer::depth     (vp);

  using namespace hugh::render::software::test;

  (*ppl.depthbuffer)->clear(); process_point_list    (ppl);
  (*ppl.depthbuffer)->clear(); process_line_list     (ppl);
  (*ppl.depthbuffer)->clear(); process_line_strip    (ppl);
  (*ppl.depthbuffer)->clear(); process_triangle_list (ppl);
  (*ppl.depthbuffer)->clear(); process_triangle_strip(ppl);
}
<|endoftext|>


<commit_before>/******************************************************************************
 *                       ____    _    _____                                   *
 *                      / ___|  / \  |  ___|    C++                           *
 *                     | |     / _ \ | |_       Actor                         *
 *                     | |___ / ___ \|  _|      Framework                     *
 *                      \____/_/   \_|_|                                      *
 *                                                                            *
 * Copyright (C) 2011 - 2017                                                  *
 * Dominik Charousset <dominik.charousset (at) haw-hamburg.de>                *
 *                                                                            *
 * Distributed under the terms and conditions of the BSD 3-Clause License or  *
 * (at your option) under the terms and conditions of the Boost Software      *
 * License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE.       *
 *                                                                            *
 * If you did not receive a copy of the license files, see                    *
 * http://opensource.org/licenses/BSD-3-Clause and                            *
 * http://www.boost.org/LICENSE_1_0.txt.                                      *
 ******************************************************************************/

#ifndef CAF_SCHEDULER_COORDINATOR_HPP
#define CAF_SCHEDULER_COORDINATOR_HPP

#include "caf/config.hpp"

#include <thread>
#include <limits>
#include <memory>
#include <condition_variable>

#include "caf/scheduler/worker.hpp"
#include "caf/scheduler/abstract_coordinator.hpp"

namespace caf {
namespace scheduler {

/// Policy-based implementation of the abstract coordinator base class.
template <class Policy>
class coordinator : public abstract_coordinator {
public:
  using super = abstract_coordinator;

  using policy_data = typename Policy::coordinator_data;

  coordinator(actor_system& sys) : super(sys), data_(this) {
    // nop
  }

  using worker_type = worker<Policy>;

  worker_type* worker_by_id(size_t x) {
    return workers_[x].get();
  }

  policy_data& data() {
    return data_;
  }

protected:
  void start() override {
    // initialize workers vector
    auto num = num_workers();
    workers_.reserve(num);
    for (size_t i = 0; i < num; ++i)
      workers_.emplace_back(new worker_type(i, this, max_throughput_));
    // start all workers now that all workers have been initialized
    for (auto& w : workers_)
      w->start();
    // run remaining startup code
    super::start();
  }

  void stop() override {
    // shutdown workers
    class shutdown_helper : public resumable, public ref_counted {
    public:
      resumable::resume_result resume(execution_unit* ptr, size_t) override {
        CAF_ASSERT(ptr != nullptr);
        std::unique_lock<std::mutex> guard(mtx);
        last_worker = ptr;
        cv.notify_all();
        return resumable::shutdown_execution_unit;
      }
      void intrusive_ptr_add_ref_impl() override {
        intrusive_ptr_add_ref(this);
      }

      void intrusive_ptr_release_impl() override {
        intrusive_ptr_release(this);
      }
      shutdown_helper() : last_worker(nullptr) {
        // nop
      }
      std::mutex mtx;
      std::condition_variable cv;
      execution_unit* last_worker;
    };
    // use a set to keep track of remaining workers
    shutdown_helper sh;
    std::set<worker_type*> alive_workers;
    auto num = num_workers();
    for (size_t i = 0; i < num; ++i) {
      alive_workers.insert(worker_by_id(i));
      sh.ref(); // make sure reference count is high enough
    }
    while (!alive_workers.empty()) {
      (*alive_workers.begin())->external_enqueue(&sh);
      // since jobs can be stolen, we cannot assume that we have
      // actually shut down the worker we've enqueued sh to
      { // lifetime scope of guard
        std::unique_lock<std::mutex> guard(sh.mtx);
        sh.cv.wait(guard, [&] { return sh.last_worker != nullptr; });
      }
      alive_workers.erase(static_cast<worker_type*>(sh.last_worker));
      sh.last_worker = nullptr;
    }
    // shutdown utility actors
    stop_actors();
    // wait until all workers are done
    for (auto& w : workers_) {
      w->get_thread().join();
    }
    // run cleanup code for each resumable
    auto f = &abstract_coordinator::cleanup_and_release;
    for (auto& w : workers_)
      policy_.foreach_resumable(w.get(), f);
    policy_.foreach_central_resumable(this, f);
  }

  void enqueue(resumable* ptr) override {
    policy_.central_enqueue(this, ptr);
  }

private:
  // usually of size std::thread::hardware_concurrency()
  std::vector<std::unique_ptr<worker_type>> workers_;
  // policy-specific data
  policy_data data_;
  // instance of our policy object
  Policy policy_;
};

} // namespace scheduler
} // namespace caf

#endif // CAF_SCHEDULER_COORDINATOR_HPP
<commit_msg>Fix API for loading custom scheduler policies<commit_after>/******************************************************************************
 *                       ____    _    _____                                   *
 *                      / ___|  / \  |  ___|    C++                           *
 *                     | |     / _ \ | |_       Actor                         *
 *                     | |___ / ___ \|  _|      Framework                     *
 *                      \____/_/   \_|_|                                      *
 *                                                                            *
 * Copyright (C) 2011 - 2017                                                  *
 * Dominik Charousset <dominik.charousset (at) haw-hamburg.de>                *
 *                                                                            *
 * Distributed under the terms and conditions of the BSD 3-Clause License or  *
 * (at your option) under the terms and conditions of the Boost Software      *
 * License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE.       *
 *                                                                            *
 * If you did not receive a copy of the license files, see                    *
 * http://opensource.org/licenses/BSD-3-Clause and                            *
 * http://www.boost.org/LICENSE_1_0.txt.                                      *
 ******************************************************************************/

#ifndef CAF_SCHEDULER_COORDINATOR_HPP
#define CAF_SCHEDULER_COORDINATOR_HPP

#include "caf/config.hpp"

#include <thread>
#include <limits>
#include <memory>
#include <condition_variable>

#include "caf/scheduler/worker.hpp"
#include "caf/scheduler/abstract_coordinator.hpp"

namespace caf {
namespace scheduler {

/// Policy-based implementation of the abstract coordinator base class.
template <class Policy>
class coordinator : public abstract_coordinator {
public:
  using super = abstract_coordinator;

  using policy_data = typename Policy::coordinator_data;

  coordinator(actor_system& sys) : super(sys), data_(this) {
    // nop
  }

  using worker_type = worker<Policy>;

  worker_type* worker_by_id(size_t x) {
    return workers_[x].get();
  }

  policy_data& data() {
    return data_;
  }

  static actor_system::module* make(actor_system& sys, detail::type_list<>) {
    return new coordinator(sys);
  }

protected:
  void start() override {
    // initialize workers vector
    auto num = num_workers();
    workers_.reserve(num);
    for (size_t i = 0; i < num; ++i)
      workers_.emplace_back(new worker_type(i, this, max_throughput_));
    // start all workers now that all workers have been initialized
    for (auto& w : workers_)
      w->start();
    // run remaining startup code
    super::start();
  }

  void stop() override {
    // shutdown workers
    class shutdown_helper : public resumable, public ref_counted {
    public:
      resumable::resume_result resume(execution_unit* ptr, size_t) override {
        CAF_ASSERT(ptr != nullptr);
        std::unique_lock<std::mutex> guard(mtx);
        last_worker = ptr;
        cv.notify_all();
        return resumable::shutdown_execution_unit;
      }
      void intrusive_ptr_add_ref_impl() override {
        intrusive_ptr_add_ref(this);
      }

      void intrusive_ptr_release_impl() override {
        intrusive_ptr_release(this);
      }
      shutdown_helper() : last_worker(nullptr) {
        // nop
      }
      std::mutex mtx;
      std::condition_variable cv;
      execution_unit* last_worker;
    };
    // use a set to keep track of remaining workers
    shutdown_helper sh;
    std::set<worker_type*> alive_workers;
    auto num = num_workers();
    for (size_t i = 0; i < num; ++i) {
      alive_workers.insert(worker_by_id(i));
      sh.ref(); // make sure reference count is high enough
    }
    while (!alive_workers.empty()) {
      (*alive_workers.begin())->external_enqueue(&sh);
      // since jobs can be stolen, we cannot assume that we have
      // actually shut down the worker we've enqueued sh to
      { // lifetime scope of guard
        std::unique_lock<std::mutex> guard(sh.mtx);
        sh.cv.wait(guard, [&] { return sh.last_worker != nullptr; });
      }
      alive_workers.erase(static_cast<worker_type*>(sh.last_worker));
      sh.last_worker = nullptr;
    }
    // shutdown utility actors
    stop_actors();
    // wait until all workers are done
    for (auto& w : workers_) {
      w->get_thread().join();
    }
    // run cleanup code for each resumable
    auto f = &abstract_coordinator::cleanup_and_release;
    for (auto& w : workers_)
      policy_.foreach_resumable(w.get(), f);
    policy_.foreach_central_resumable(this, f);
  }

  void enqueue(resumable* ptr) override {
    policy_.central_enqueue(this, ptr);
  }

private:
  // usually of size std::thread::hardware_concurrency()
  std::vector<std::unique_ptr<worker_type>> workers_;
  // policy-specific data
  policy_data data_;
  // instance of our policy object
  Policy policy_;
};

} // namespace scheduler
} // namespace caf

#endif // CAF_SCHEDULER_COORDINATOR_HPP
<|endoftext|>