<commit_before>#include "core/matrix.h"
#include "core/quat.h"
#include "core/vec3.h"

namespace Lux
{

const Matrix Matrix::IDENTITY(
	1, 0, 0, 0,
	0, 1, 0, 0,
	0, 0, 1, 0,
	0, 0, 0, 1
);

void multiplicate(Matrix& result, const Matrix& op1, const Matrix& op2)
{
	ASSERT(&result != &op2);
	ASSERT(&result != &op1); // use operator *

	/// TODO optimize
	result.m11 = op1.m11 * op2.m11 + op1.m21 * op2.m12 + op1.m31 * op2.m13 + op1.m41 * op2.m14;
	result.m21 = op1.m11 * op2.m21 + op1.m21 * op2.m22 + op1.m31 * op2.m23 + op1.m41 * op2.m24;
	result.m31 = op1.m11 * op2.m31 + op1.m21 * op2.m32 + op1.m31 * op2.m33 + op1.m41 * op2.m34;
	result.m41 = op1.m11 * op2.m41 + op1.m21 * op2.m42 + op1.m31 * op2.m43 + op1.m41 * op2.m44;

	result.m12 = op1.m12 * op2.m11 + op1.m22 * op2.m12 + op1.m32 * op2.m13 + op1.m42 * op2.m14;
	result.m22 = op1.m12 * op2.m21 + op1.m22 * op2.m22 + op1.m32 * op2.m23 + op1.m42 * op2.m24;
	result.m32 = op1.m12 * op2.m31 + op1.m22 * op2.m32 + op1.m32 * op2.m33 + op1.m42 * op2.m34;
	result.m42 = op1.m12 * op2.m41 + op1.m22 * op2.m42 + op1.m32 * op2.m43 + op1.m42 * op2.m44;

	result.m13 = op1.m13 * op2.m11 + op1.m23 * op2.m12 + op1.m33 * op2.m13 + op1.m43 * op2.m14;
	result.m23 = op1.m13 * op2.m21 + op1.m23 * op2.m22 + op1.m33 * op2.m23 + op1.m43 * op2.m24;
	result.m33 = op1.m13 * op2.m31 + op1.m23 * op2.m32 + op1.m33 * op2.m33 + op1.m43 * op2.m34;
	result.m43 = op1.m13 * op2.m41 + op1.m23 * op2.m42 + op1.m33 * op2.m43 + op1.m43 * op2.m44;

	result.m14 = op1.m14 * op2.m11 + op1.m24 * op2.m12 + op1.m34 * op2.m13 + op1.m44 * op2.m14;
	result.m24 = op1.m14 * op2.m21 + op1.m24 * op2.m22 + op1.m34 * op2.m23 + op1.m44 * op2.m24;
	result.m34 = op1.m14 * op2.m31 + op1.m24 * op2.m32 + op1.m34 * op2.m33 + op1.m44 * op2.m34;
	result.m44 = op1.m14 * op2.m41 + op1.m24 * op2.m42 + op1.m34 * op2.m43 + op1.m44 * op2.m44;
}

Matrix Matrix::operator *(const Matrix& rhs) const
{
	return Matrix(
		this->m11 * rhs.m11 + this->m21 * rhs.m12 + this->m31 * rhs.m13 + this->m41 * rhs.m14,
		this->m12 * rhs.m11 + this->m22 * rhs.m12 + this->m32 * rhs.m13 + this->m42 * rhs.m14,
		this->m13 * rhs.m11 + this->m23 * rhs.m12 + this->m33 * rhs.m13 + this->m43 * rhs.m14,
		this->m14 * rhs.m11 + this->m24 * rhs.m12 + this->m34 * rhs.m13 + this->m44 * rhs.m14,

		this->m11 * rhs.m21 + this->m21 * rhs.m22 + this->m31 * rhs.m23 + this->m41 * rhs.m24,
		this->m12 * rhs.m21 + this->m22 * rhs.m22 + this->m32 * rhs.m23 + this->m42 * rhs.m24,
		this->m13 * rhs.m21 + this->m23 * rhs.m22 + this->m33 * rhs.m23 + this->m43 * rhs.m24,
		this->m14 * rhs.m21 + this->m24 * rhs.m22 + this->m34 * rhs.m23 + this->m44 * rhs.m24,

		this->m11 * rhs.m31 + this->m21 * rhs.m32 + this->m31 * rhs.m33 + this->m41 * rhs.m34,
		this->m12 * rhs.m31 + this->m22 * rhs.m32 + this->m32 * rhs.m33 + this->m42 * rhs.m34,
		this->m13 * rhs.m31 + this->m23 * rhs.m32 + this->m33 * rhs.m33 + this->m43 * rhs.m34,
		this->m14 * rhs.m31 + this->m24 * rhs.m32 + this->m34 * rhs.m33 + this->m44 * rhs.m34,

		this->m11 * rhs.m41 + this->m21 * rhs.m42 + this->m31 * rhs.m43 + this->m41 * rhs.m44,
		this->m12 * rhs.m41 + this->m22 * rhs.m42 + this->m32 * rhs.m43 + this->m42 * rhs.m44,
		this->m13 * rhs.m41 + this->m23 * rhs.m42 + this->m33 * rhs.m43 + this->m43 * rhs.m44,
		this->m14 * rhs.m41 + this->m24 * rhs.m42 + this->m34 * rhs.m43 + this->m44 * rhs.m44
	);
}

void Matrix::getTranslation(Vec3& pos) const
{
	pos.x = m41;
	pos.y = m42;
	pos.z = m43;
}

Vec3 Matrix::getTranslation() const
{
	return Vec3(m41, m42, m43);
}

void Matrix::getRotation(Quat& rot) const
{
	float tr = m11 + m22 + m33;

	if (tr > 0)
	{
		float S = sqrt(tr+1.0f) * 2;
		rot.w = 0.25f * S;
		rot.x = (m23 - m32) / S;
		rot.y = (m31 - m13) / S;
		rot.z = (m12 - m21) / S;
	}
	else if ((m11 > m22)&(m11 > m33))
	{
		float S = sqrt(1.0f + m11 - m22 - m33) * 2;
		rot.w = (m23 - m32) / S;
		rot.x = 0.25f * S;
		rot.y = (m21 + m12) / S;
		rot.z = (m31 + m13) / S;
	}
	else if (m22 > m33)
	{
		float S = sqrt(1.0f + m22 - m11 - m33) * 2;
		rot.w = (m31 - m13) / S;
		rot.x = (m32 + m12) / S;
		rot.y = 0.25f * S;
		rot.z = (m32 + m23) / S;
	}
	else
	{
		float S = sqrt(1.0f + m33 - m11 - m22) * 2;
		rot.w = (m12 - m21) / S;
		rot.x = (m31 + m13) / S;
		rot.y = (m32 + m23) / S;
		rot.z = 0.25f * S;
	}
}

void Matrix::transpose()
{
		float tmp = m21;
		m21 = m12;
		m12 = tmp;

		tmp = m32;
		m32 = m23;
		m23 = tmp;

		tmp = m31;
		m31 = m13;
		m13 = tmp;

		tmp = m41;
		m41 = m14;
		m14 = tmp;

		tmp = m42;
		m42 = m24;
		m24 = tmp;

		tmp = m43;
		m43 = m34;
		m34 = tmp;
}

Vec3 Matrix::mutliplyPosition(const Vec3& rhs)
{
	return Vec3(
		m11 * rhs.x + m21 * rhs.y + m31 * rhs.z + m41,
		m12 * rhs.x + m22 * rhs.y + m32 * rhs.z + m42,
		m13 * rhs.x + m23 * rhs.y + m33 * rhs.z + m43
	);
}

void Matrix::setIdentity(Matrix& mtx)
{
	mtx.m11 = 1; mtx.m12 = 0; mtx.m13 = 0; mtx.m14 = 0;
	mtx.m21 = 0; mtx.m22 = 1; mtx.m23 = 0; mtx.m24 = 0;
	mtx.m31 = 0; mtx.m32 = 0; mtx.m33 = 1; mtx.m34 = 0;
	mtx.m41 = 0; mtx.m42 = 0; mtx.m43 = 0; mtx.m44 = 1;
}

} // !namespace Lux<commit_msg>fixed matrix-to-quaternion conversion<commit_after>#include "core/matrix.h"
#include "core/quat.h"
#include "core/vec3.h"

namespace Lux
{

const Matrix Matrix::IDENTITY(
	1, 0, 0, 0,
	0, 1, 0, 0,
	0, 0, 1, 0,
	0, 0, 0, 1
);

void multiplicate(Matrix& result, const Matrix& op1, const Matrix& op2)
{
	ASSERT(&result != &op2);
	ASSERT(&result != &op1); // use operator *

	/// TODO optimize
	result.m11 = op1.m11 * op2.m11 + op1.m21 * op2.m12 + op1.m31 * op2.m13 + op1.m41 * op2.m14;
	result.m21 = op1.m11 * op2.m21 + op1.m21 * op2.m22 + op1.m31 * op2.m23 + op1.m41 * op2.m24;
	result.m31 = op1.m11 * op2.m31 + op1.m21 * op2.m32 + op1.m31 * op2.m33 + op1.m41 * op2.m34;
	result.m41 = op1.m11 * op2.m41 + op1.m21 * op2.m42 + op1.m31 * op2.m43 + op1.m41 * op2.m44;

	result.m12 = op1.m12 * op2.m11 + op1.m22 * op2.m12 + op1.m32 * op2.m13 + op1.m42 * op2.m14;
	result.m22 = op1.m12 * op2.m21 + op1.m22 * op2.m22 + op1.m32 * op2.m23 + op1.m42 * op2.m24;
	result.m32 = op1.m12 * op2.m31 + op1.m22 * op2.m32 + op1.m32 * op2.m33 + op1.m42 * op2.m34;
	result.m42 = op1.m12 * op2.m41 + op1.m22 * op2.m42 + op1.m32 * op2.m43 + op1.m42 * op2.m44;

	result.m13 = op1.m13 * op2.m11 + op1.m23 * op2.m12 + op1.m33 * op2.m13 + op1.m43 * op2.m14;
	result.m23 = op1.m13 * op2.m21 + op1.m23 * op2.m22 + op1.m33 * op2.m23 + op1.m43 * op2.m24;
	result.m33 = op1.m13 * op2.m31 + op1.m23 * op2.m32 + op1.m33 * op2.m33 + op1.m43 * op2.m34;
	result.m43 = op1.m13 * op2.m41 + op1.m23 * op2.m42 + op1.m33 * op2.m43 + op1.m43 * op2.m44;

	result.m14 = op1.m14 * op2.m11 + op1.m24 * op2.m12 + op1.m34 * op2.m13 + op1.m44 * op2.m14;
	result.m24 = op1.m14 * op2.m21 + op1.m24 * op2.m22 + op1.m34 * op2.m23 + op1.m44 * op2.m24;
	result.m34 = op1.m14 * op2.m31 + op1.m24 * op2.m32 + op1.m34 * op2.m33 + op1.m44 * op2.m34;
	result.m44 = op1.m14 * op2.m41 + op1.m24 * op2.m42 + op1.m34 * op2.m43 + op1.m44 * op2.m44;
}

Matrix Matrix::operator *(const Matrix& rhs) const
{
	return Matrix(
		this->m11 * rhs.m11 + this->m21 * rhs.m12 + this->m31 * rhs.m13 + this->m41 * rhs.m14,
		this->m12 * rhs.m11 + this->m22 * rhs.m12 + this->m32 * rhs.m13 + this->m42 * rhs.m14,
		this->m13 * rhs.m11 + this->m23 * rhs.m12 + this->m33 * rhs.m13 + this->m43 * rhs.m14,
		this->m14 * rhs.m11 + this->m24 * rhs.m12 + this->m34 * rhs.m13 + this->m44 * rhs.m14,

		this->m11 * rhs.m21 + this->m21 * rhs.m22 + this->m31 * rhs.m23 + this->m41 * rhs.m24,
		this->m12 * rhs.m21 + this->m22 * rhs.m22 + this->m32 * rhs.m23 + this->m42 * rhs.m24,
		this->m13 * rhs.m21 + this->m23 * rhs.m22 + this->m33 * rhs.m23 + this->m43 * rhs.m24,
		this->m14 * rhs.m21 + this->m24 * rhs.m22 + this->m34 * rhs.m23 + this->m44 * rhs.m24,

		this->m11 * rhs.m31 + this->m21 * rhs.m32 + this->m31 * rhs.m33 + this->m41 * rhs.m34,
		this->m12 * rhs.m31 + this->m22 * rhs.m32 + this->m32 * rhs.m33 + this->m42 * rhs.m34,
		this->m13 * rhs.m31 + this->m23 * rhs.m32 + this->m33 * rhs.m33 + this->m43 * rhs.m34,
		this->m14 * rhs.m31 + this->m24 * rhs.m32 + this->m34 * rhs.m33 + this->m44 * rhs.m34,

		this->m11 * rhs.m41 + this->m21 * rhs.m42 + this->m31 * rhs.m43 + this->m41 * rhs.m44,
		this->m12 * rhs.m41 + this->m22 * rhs.m42 + this->m32 * rhs.m43 + this->m42 * rhs.m44,
		this->m13 * rhs.m41 + this->m23 * rhs.m42 + this->m33 * rhs.m43 + this->m43 * rhs.m44,
		this->m14 * rhs.m41 + this->m24 * rhs.m42 + this->m34 * rhs.m43 + this->m44 * rhs.m44
	);
}

void Matrix::getTranslation(Vec3& pos) const
{
	pos.x = m41;
	pos.y = m42;
	pos.z = m43;
}

Vec3 Matrix::getTranslation() const
{
	return Vec3(m41, m42, m43);
}

void Matrix::getRotation(Quat& rot) const
{
	float tr = 1 + m11 + m22 + m33;

	if (tr > 0)
	{
		float S = sqrt(tr) * 2;
		rot.w = 0.25f * S;
		rot.x = (m23 - m32) / S;
		rot.y = (m31 - m13) / S;
		rot.z = (m12 - m21) / S;
	}
	else if ((m11 > m22)&(m11 > m33))
	{
		float S = sqrt(1.0f + m11 - m22 - m33) * 2;
		rot.w = (m32 - m23) / S;
		rot.x = 0.25f * S;
		rot.y = (m12 + m21) / S;
		rot.z = (m13 + m31) / S;
	}
	else if (m22 > m33)
	{
		float S = sqrt(1.0f + m22 - m11 - m33) * 2;
		rot.w = (m13 - m31) / S;
		rot.x = (m12 + m21) / S;
		rot.y = 0.25f * S;
		rot.z = (m23 + m32) / S;
	}
	else
	{
		float S = sqrt(1.0f + m33 - m11 - m22) * 2;
		rot.w = (m21 - m21) / S;
		rot.x = (m31 + m13) / S;
		rot.y = (m32 + m23) / S;
		rot.z = 0.25f * S;
	}
}

void Matrix::transpose()
{
		float tmp = m21;
		m21 = m12;
		m12 = tmp;

		tmp = m32;
		m32 = m23;
		m23 = tmp;

		tmp = m31;
		m31 = m13;
		m13 = tmp;

		tmp = m41;
		m41 = m14;
		m14 = tmp;

		tmp = m42;
		m42 = m24;
		m24 = tmp;

		tmp = m43;
		m43 = m34;
		m34 = tmp;
}

Vec3 Matrix::mutliplyPosition(const Vec3& rhs)
{
	return Vec3(
		m11 * rhs.x + m21 * rhs.y + m31 * rhs.z + m41,
		m12 * rhs.x + m22 * rhs.y + m32 * rhs.z + m42,
		m13 * rhs.x + m23 * rhs.y + m33 * rhs.z + m43
	);
}

void Matrix::setIdentity(Matrix& mtx)
{
	mtx.m11 = 1; mtx.m12 = 0; mtx.m13 = 0; mtx.m14 = 0;
	mtx.m21 = 0; mtx.m22 = 1; mtx.m23 = 0; mtx.m24 = 0;
	mtx.m31 = 0; mtx.m32 = 0; mtx.m33 = 1; mtx.m34 = 0;
	mtx.m41 = 0; mtx.m42 = 0; mtx.m43 = 0; mtx.m44 = 1;
}

} // !namespace Lux<|endoftext|>


<commit_before>#include <cmath>
#include "solver.hpp"

namespace oplin{

using std::cout;
using std::endl;
using std::cerr;
using namespace Eigen;

SolverBase::~SolverBase(){}
GradientDescent::~GradientDescent(){}
/**
 * Line search:
 *   The basic line search form would be: x_{k+1} = x_k + p_k * alpha_k
 *   The typical form of p will be p_k = -B_k^(-1) * grad(f_k)
 *   B_k is always a symmetric and nonsingular matrix.
 *
 * @param problem Problem instance
 * @param w       weights for optimization
 * @param alpha   step size of line search
 *
 */
size_t
SolverBase::line_search(ProblemPtr problem, Eigen::Ref<ColVector>w, double& alpha)
{
    const double c1 = 1e-4;
    double backoff = 0.5;
    const double dir_derivative = steepest_grad_.transpose() * p_;
    if (epoch_==1)
    {
        double norm_p = sqrt(p_.squaredNorm());
        alpha = (1 / norm_p);
        backoff = 0.1;
    }
    // check p is descent direction
    if(dir_derivative >= 0)
    {
        cerr << "SolverBase::line_search : non-descent direction is chosen in line search ("
             << __FILE__ << ", line " << __LINE__ << ")."<< endl;
        throw(std::runtime_error("non-descent direction is chosen in line search, check gradient!"));
    }

    // armijo condition solved by backtracing approach
    // f(x_k + a*p_k) <= f(x_k) + c*a*Delta(f_k)^T * p_k
    size_t iter=0;
    // cout << "++++++++++p++++++++++\n" << p_ << "\n+++++++++++++++++++++"<<endl;
    while(true)
    {
        // update w with search direction(p) and step size(alpha)
        problem->update_weights(next_w_, w, p_, alpha);
        next_loss_ = problem->loss(next_w_);
        // cout << "next_loss: " << next_loss_ << " | sufficient_desc: " << loss_+dir_derivative * alpha << endl;
        if(next_loss_ <= loss_ + c1 * dir_derivative * alpha) break;
        alpha *= backoff;
        iter++;
    }

    return iter;
}

/**
 * Solve the problem on dataset with parameters
 *
 * @param problem Problem instance
 * @param param   Parameter instance
 * @param w       weights for optimize
 *
 */
void
GradientDescent::solve(ProblemPtr problem, ParamPtr param, Eigen::Ref<ColVector>& w)
{

    // initializations
    loss_ = problem->loss(w);
    steepest_grad_ = ColVector::Zero(w.rows(),1);
    problem->gradient(w, steepest_grad_);
    problem->regularized_gradient(w, steepest_grad_);
    // next_grad_ = ColVector::Zero(w.rows(),1);
    next_loss_ = loss_;
    next_w_ = w;
    double rela_improve = 0;
    double alpha;
    size_t iter = 0;

    // check if the weights already optimized
    if(loss_ < param->abs_tol)
    {
        return;
        VOUT("Already optimized weights get!");
    }

    // -- debug print
    VOUT("\n*** To disable debug info: $ make DISABLE_DEBUG=yes ***\n");
    VOUT("|%5s|%15s|%15s|%5s|\n","Epoch","Loss","Improve","#iter");

    for(epoch_ = 0; epoch_ < param->max_epoch; ++epoch_)
    {

        /*** Iteration - k ***/

        /// 01 - Update line search direction p
        //     |- for steepest gradient descent method, p is simply gradient direction
        p_ = (-1) * steepest_grad_;
        //     |- line search on p and update w and loss values
        alpha = 1.0;
        iter = this->line_search(problem, w, alpha);

        /// 02 - Termination Check
        rela_improve = fabs(next_loss_ - loss_);
        VOUT("|%5d|%15.4f|%15.6f|%5d|\n",epoch_,next_loss_,rela_improve,iter);
        if(rela_improve < param->rela_tol || next_loss_ < param->abs_tol)
        {
            // assign next_w_ to w as return value
            w.swap(next_w_);
            break;
        }

        /// 03 - Update varaiables
        problem->gradient(next_w_, steepest_grad_);
        problem->regularized_gradient(next_w_, steepest_grad_);
        loss_ = next_loss_;
        w.swap(next_w_);
        // grad_.swap(next_grad_);
    }
}

} // oplin
<commit_msg>no update<commit_after>#include <cmath>
#include "solver.hpp"

namespace oplin{

using std::cout;
using std::endl;
using std::cerr;
using namespace Eigen;

SolverBase::~SolverBase(){}
GradientDescent::~GradientDescent(){}
/**
 * Line search:
 *   The basic line search form would be: x_{k+1} = x_k + p_k * alpha_k
 *   The typical form of p will be p_k = -B_k^(-1) * grad(f_k)
 *   B_k is always a symmetric and nonsingular matrix.
 *
 * @param problem Problem instance
 * @param w       weights for optimization
 * @param alpha   step size of line search
 *
 */
size_t
SolverBase::line_search(ProblemPtr problem, Eigen::Ref<ColVector>w, double& alpha)
{
    const double c1 = 1e-4;
    double backoff = 0.5;
    const double dir_derivative = steepest_grad_.transpose() * p_;
    if (epoch_==1)
    {
        double norm_p = sqrt(p_.squaredNorm());
        alpha = (1 / norm_p);
        backoff = 0.1;
    }
    // check p is descent direction
    if(dir_derivative >= 0)
    {
        cerr << "SolverBase::line_search : non-descent direction is chosen in line search ("
             << __FILE__ << ", line " << __LINE__ << ")."<< endl;
        throw(std::runtime_error("non-descent direction is chosen in line search, check gradient!"));
    }

    // armijo condition solved by backtracing approach
    // f(x_k + a*p_k) <= f(x_k) + c*a*Delta(f_k)^T * p_k
    size_t iter=0;
    // cout << "++++++++++p++++++++++\n" << p_ << "\n+++++++++++++++++++++"<<endl;
    while(true)
    {
        // update w with search direction(p) and step size(alpha)
        problem->update_weights(next_w_, w, p_, alpha);
        next_loss_ = problem->loss(next_w_);
        // cout << "next_loss: " << next_loss_ << " | sufficient_desc: " << loss_+dir_derivative * alpha << endl;
        if(next_loss_ <= loss_ + c1 * dir_derivative * alpha) break;
        alpha *= backoff;
        iter++;
    }

    return iter;
}

/**
 * Solve the problem on dataset with parameters
 *
 * @param problem Problem instance
 * @param param   Parameter instance
 * @param w       weights for optimize
 *
 */
void
GradientDescent::solve(ProblemPtr problem, ParamPtr param, Eigen::Ref<ColVector>& w)
{

    // initializations
    loss_ = problem->loss(w);
    steepest_grad_ = ColVector::Zero(w.rows(),1);
    problem->gradient(w, steepest_grad_);
    problem->regularized_gradient(w, steepest_grad_);
    // next_grad_ = ColVector::Zero(w.rows(),1);
    next_loss_ = loss_;
    next_w_ = w;
    double rela_improve = 0;
    double alpha;
    size_t iter = 0;

    // check if the weights already optimized
    if(loss_ < param->abs_tol)
    {
        return;
        VOUT("Already optimized weights get!");
    }

    // -- debug print
    VOUT("\n*** To disable debug info: $ make DISABLE_DEBUG=yes ***\n");
    VOUT("|%5s|%15s|%15s|%5s|\n","Epoch","Loss","Improve","#iter");

    for(epoch_ = 0; epoch_ < param->max_epoch; ++epoch_)
    {

        /*** Iteration - k ***/

        /// 01 - Update line search direction p
        //     |- for steepest gradient descent method, p is simply gradient direction
        p_ = (-1) * steepest_grad_;
        //     |- line search on p and update w and loss values
        alpha = 1.0;
        iter = this->line_search(problem, w, alpha);

        /// 02 - Termination Check
        rela_improve = fabs(next_loss_ - loss_);
        VOUT("|%5d|%15.4f|%15.6f|%5d|\n",epoch_,next_loss_,rela_improve,iter);
        if(rela_improve < param->rela_tol || next_loss_ < param->abs_tol)
        {
            // assign next_w_ to w as return value
            w.swap(next_w_);
            break;
        }

        /// 03 - Update varaiables
        problem->gradient(next_w_, steepest_grad_);
        problem->regularized_gradient(next_w_, steepest_grad_);
        loss_ = next_loss_;
        w.swap(next_w_);
        // grad_.swap(next_grad_);
    }
}

} // oplin
<|endoftext|>


<commit_before>/* ========================================================================= *
 * File: memory_notification.cpp
 *
 * This file is part of Memory Notification Library (libmemnotifyqt)
 *
 * Copyright (C) 2010 Nokia Corporation. All rights reserved.
 *
 * Contacts: Leonid Moiseichuk <leonid.moiseichuk@nokia.com>
 *
 * 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., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA
 * ========================================================================= */

/* ========================================================================= *
* Includes.
* ========================================================================= */

#include <sys/types.h>
#include <aio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <QSettings>
#include <memnotify/watcher_builder.hpp>
#include <memnotify/memory_notification.hpp>
#include "poller.hpp"

BEGIN_MEMNOTIFY_NAMESPACE

/* ========================================================================= *
* Class MemoryNotification.
* ========================================================================= */

MemoryNotification*  MemoryNotification :: ourMemoryNotification = NULL;

bool MemoryNotification :: setup(const char* pathSpecification)
{
  /* We should disable functionality if it is enabled */
  if (myEnabled && !disable())
    return false;

  /* If no files pointed the default file should be loaded */
  if ( !(pathSpecification && *pathSpecification) )
    pathSpecification = "default";

  /* if we have some watchers in list - they must be removed */
  clearWatchers();

  const QStringList files = QString(pathSpecification).split(":", QString::SkipEmptyParts);

  foreach(QString file, files)
  {
    char  filePath[BUFSIZ];

    if ( !Platform::defaultObject().path(file.toAscii().constData(), filePath, sizeof(filePath)) )
    {
#if MEMNOTIFY_DUMP
      printf ("* cannot resolve %s as a valid path (%s) => skipped\n", file.toAscii().constData(), filePath);
      continue;
#endif
    }

    const QSettings   config(filePath, QSettings::IniFormat);
    /* array with names of thresholds */
    const QStringList tholds(config.childGroups());

    /* Now trying to build the watchers, one by one */
    foreach(QString thold, tholds)
    {
      Watcher* newcomer = WatcherBuilder::build(config, thold);

      /* Watcher might be disabled in configuration file */
      if ( newcomer )
      {
#if MEMNOTIFY_DUMP
        const bool newcomerIsValid = newcomer->valid();
        if ( !newcomerIsValid )
        {
          newcomer->dump();
          Q_ASSERT(true == newcomerIsValid);
        }
#endif
        myWatchers.append(newcomer);
      }
    } /* for each thold */
  } /* for each file */

  /* As a result we must have at least one watcher created */
  return !myWatchers.isEmpty();
} /* setup */

bool MemoryNotification :: poll()
{
  /* we should be enabled first */
  if (!myEnabled )
    return false;

  /* that is strange but possible */
  if ( myPoller )
  {
    if ( myPoller->isRunning() )
      return true;
    /* poller needs to be re-created */
    myPoller->terminate();
    delete myPoller;
    myPoller = NULL;
  }

  /* collect the handlers */
  int  handlers[ myWatchers.count() ];
  const uint counter = query(handlers, myWatchers.count());

  if ( !counter )
    return false;

  /* Now construct the poller object */
  myPoller = new Poller(this, handlers, counter);
  QThread::yieldCurrentThread();
  return (myPoller && myPoller->isRunning());
} /* poll */

uint MemoryNotification :: query(int* fds, uint size)
{
  uint counter = 0;
  if (myEnabled && fds && myWatchers.count() <= (int)size)
  {
    foreach(const Watcher* watcher, myWatchers)
    {
      const int handler = (watcher ? watcher->handler() : -1);
      if ( handler < 0 )
        return 0;
      fds[counter++] = handler;
    }
  }

  return counter;
} /* query */

bool MemoryNotification :: process(const int* fds, uint counter)
{
  /* we should be enabled */
  if ( !myEnabled )
    return false;

  /* Check the parameters */
  if ( !fds )
    return false;

  if ( !counter )
    return true;

  /* result of processing, should be true if all watchers handled OK */
  bool result = true;
  QList<Watcher*> updated;

  /* And now handling the all incoming events */
  for (uint ifd = 0; ifd < counter; ifd++)
  {
    const int fd = fds[ifd];

    /* First - we should find the watcher */
    foreach(Watcher* watcher, myWatchers)
    {
      Q_ASSERT(NULL != watcher);
      if (watcher && fd == watcher->handler())
      {
        const bool oldState = watcher->state();
        if ( watcher->process() )
        {
          if (oldState != watcher->state())
            updated.append(watcher);
        }
        else
        {
          /* we are failed with processing but we must continue until the end */
          result = false;
        }
      }
    } /* scan for watcher */
  } /* for each file descriptor */

  /* Now we have list of updated watchers -> sending the notifications */
  foreach(const Watcher* watcher, updated)
  {
    Q_ASSERT(NULL != watcher);
    const QString& name  = watcher->name();
    const bool     state = watcher->state();

    /* if necessary - notify callbacks */
    if (myObservers.count() > 0)
    {
      foreach(OBSERVER observer, myObservers)
      {
        Q_ASSERT(NULL != observer);
        if ( observer )
          observer(name, state);
      }
    }

    /* if necessary - notify subscribers */
    if (mySignalCounter > 0)
      emit notified(name, state);
  } /* for each updated */

  return result;
} /* process */

bool MemoryNotification :: enable()
{
  if ( myEnabled )
    return false;

  if (0 == mySignalCounter && myObservers.isEmpty())
    return false;

  if ( myWatchers.isEmpty() )
    return false;

  /* disable watchers one by one */
  int enabled_counter = 0;
  foreach(Watcher* watcher, myWatchers)
  {
    if (watcher && watcher->enable())
    {
      /* item successfully enabled */
      enabled_counter++;
    }
  }

  /* set common enabled flag on only if we have all items enabled */
  myEnabled = (myWatchers.count() == enabled_counter);

  /* function done if no items enabled */
  return (myEnabled);
} /* enable */

bool MemoryNotification :: disable()
{
  if ( !myEnabled )
    return false;

  /* disable watchers one by one */
  int disabled_counter = 0;
  foreach(Watcher* watcher, myWatchers)
  {
    if (watcher && watcher->disable())
    {
      /* item successfully disabled */
      disabled_counter++;
    }
  }

  /* if poller is running - remove it. Likely thread will finished already */
  if ( myPoller )
  {
    myPoller->terminate();
    delete myPoller;
    myPoller = NULL;
  }

  /* set common enabled flag off only if we have all items disabled */
  myEnabled = (myWatchers.count() != disabled_counter);

  /* function done if no items enabled */
  return (! myEnabled);
} /* disable */

bool MemoryNotification :: valid() const
{
  /* first, we must have subscribed items */
  if (0 == mySignalCounter && myObservers.isEmpty())
    return false;

  /* we must have sources for signal generation */
  if ( myWatchers.isEmpty() )
    return false;

  /* All observers must be non-null */
  if ( myObservers.indexOf(NULL) >= 0 )
    return false;

  /* All watchers must be non-null, valid and maybe enabled */
  foreach(const Watcher* watcher, myWatchers)
  {
    if (watcher && watcher->valid() && watcher->enabled() == myEnabled)
    {
      /* check the next item */
      continue;
    }
    return false;
  }

  return true;
} /* valid */

void MemoryNotification :: clearWatchers()
{
  if (myWatchers.count() > 0)
  {
    foreach (Watcher* watcher, myWatchers)
    {
      if (watcher)
        delete watcher;
    }
    myWatchers.clear();
  }
} /* clearWatchers */

void MemoryNotification :: dump() const
{
#if MEMNOTIFY_DUMP
  printf ("MemoryNotification %08x {\n", (uint)this);
  printf ("  ourMemoryNotification %08x signal counter %u enabled %d polling thread %08x\n",
          (uint)ourMemoryNotification, mySignalCounter, myEnabled, (uint)myPoller
      );

  if ( myPoller )
    printf ("  polling is running: %d\n", myPoller->isRunning());

  printf ("  observers %d {\n", myObservers.count());
  foreach (OBSERVER observer, myObservers)
  {
    printf ("\t%08x\n", (uint)observer);
  }
  printf ("  }\n");

  printf ("  watchers %d {\n", myWatchers.count());
  foreach (const Watcher* watcher, myWatchers)
  {
    printf ("\t%08x ", (uint)watcher);
    if (watcher)
      watcher->dump();
    else
      printf ("\n");
  }
  printf ("  }\n");

  printf ("}\n");
#endif /* if MEMNOTIFY_DUMP */
}

END_MEMOTIFY_NAMESPACE

/* =================[ end of file memnotify/memory_notification.cpp ]========================= */
<commit_msg>continue in MemoryNotification::setup should not be under conditional compilation<commit_after>/* ========================================================================= *
 * File: memory_notification.cpp
 *
 * This file is part of Memory Notification Library (libmemnotifyqt)
 *
 * Copyright (C) 2010 Nokia Corporation. All rights reserved.
 *
 * Contacts: Leonid Moiseichuk <leonid.moiseichuk@nokia.com>
 *
 * 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., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA
 * ========================================================================= */

/* ========================================================================= *
* Includes.
* ========================================================================= */

#include <sys/types.h>
#include <aio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <QSettings>
#include <memnotify/watcher_builder.hpp>
#include <memnotify/memory_notification.hpp>
#include "poller.hpp"

BEGIN_MEMNOTIFY_NAMESPACE

/* ========================================================================= *
* Class MemoryNotification.
* ========================================================================= */

MemoryNotification*  MemoryNotification :: ourMemoryNotification = NULL;

bool MemoryNotification :: setup(const char* pathSpecification)
{
  /* We should disable functionality if it is enabled */
  if (myEnabled && !disable())
    return false;

  /* If no files pointed the default file should be loaded */
  if ( !(pathSpecification && *pathSpecification) )
    pathSpecification = "default";

  /* if we have some watchers in list - they must be removed */
  clearWatchers();

  const QStringList files = QString(pathSpecification).split(":", QString::SkipEmptyParts);

  foreach(QString file, files)
  {
    char  filePath[BUFSIZ];

    if ( !Platform::defaultObject().path(file.toAscii().constData(), filePath, sizeof(filePath)) )
    {
#if MEMNOTIFY_DUMP
      printf ("* cannot resolve %s as a valid path (%s) => skipped\n", file.toAscii().constData(), filePath);
#endif
      continue;
    }

    const QSettings   config(filePath, QSettings::IniFormat);
    /* array with names of thresholds */
    const QStringList tholds(config.childGroups());

    /* Now trying to build the watchers, one by one */
    foreach(QString thold, tholds)
    {
      Watcher* newcomer = WatcherBuilder::build(config, thold);

      /* Watcher might be disabled in configuration file */
      if ( newcomer )
      {
#if MEMNOTIFY_DUMP
        const bool newcomerIsValid = newcomer->valid();
        if ( !newcomerIsValid )
        {
          newcomer->dump();
          Q_ASSERT(true == newcomerIsValid);
        }
#endif
        myWatchers.append(newcomer);
      }
    } /* for each thold */
  } /* for each file */

  /* As a result we must have at least one watcher created */
  return !myWatchers.isEmpty();
} /* setup */

bool MemoryNotification :: poll()
{
  /* we should be enabled first */
  if (!myEnabled )
    return false;

  /* that is strange but possible */
  if ( myPoller )
  {
    if ( myPoller->isRunning() )
      return true;
    /* poller needs to be re-created */
    myPoller->terminate();
    delete myPoller;
    myPoller = NULL;
  }

  /* collect the handlers */
  int  handlers[ myWatchers.count() ];
  const uint counter = query(handlers, myWatchers.count());

  if ( !counter )
    return false;

  /* Now construct the poller object */
  myPoller = new Poller(this, handlers, counter);
  QThread::yieldCurrentThread();
  return (myPoller && myPoller->isRunning());
} /* poll */

uint MemoryNotification :: query(int* fds, uint size)
{
  uint counter = 0;
  if (myEnabled && fds && myWatchers.count() <= (int)size)
  {
    foreach(const Watcher* watcher, myWatchers)
    {
      const int handler = (watcher ? watcher->handler() : -1);
      if ( handler < 0 )
        return 0;
      fds[counter++] = handler;
    }
  }

  return counter;
} /* query */

bool MemoryNotification :: process(const int* fds, uint counter)
{
  /* we should be enabled */
  if ( !myEnabled )
    return false;

  /* Check the parameters */
  if ( !fds )
    return false;

  if ( !counter )
    return true;

  /* result of processing, should be true if all watchers handled OK */
  bool result = true;
  QList<Watcher*> updated;

  /* And now handling the all incoming events */
  for (uint ifd = 0; ifd < counter; ifd++)
  {
    const int fd = fds[ifd];

    /* First - we should find the watcher */
    foreach(Watcher* watcher, myWatchers)
    {
      Q_ASSERT(NULL != watcher);
      if (watcher && fd == watcher->handler())
      {
        const bool oldState = watcher->state();
        if ( watcher->process() )
        {
          if (oldState != watcher->state())
            updated.append(watcher);
        }
        else
        {
          /* we are failed with processing but we must continue until the end */
          result = false;
        }
      }
    } /* scan for watcher */
  } /* for each file descriptor */

  /* Now we have list of updated watchers -> sending the notifications */
  foreach(const Watcher* watcher, updated)
  {
    Q_ASSERT(NULL != watcher);
    const QString& name  = watcher->name();
    const bool     state = watcher->state();

    /* if necessary - notify callbacks */
    if (myObservers.count() > 0)
    {
      foreach(OBSERVER observer, myObservers)
      {
        Q_ASSERT(NULL != observer);
        if ( observer )
          observer(name, state);
      }
    }

    /* if necessary - notify subscribers */
    if (mySignalCounter > 0)
      emit notified(name, state);
  } /* for each updated */

  return result;
} /* process */

bool MemoryNotification :: enable()
{
  if ( myEnabled )
    return false;

  if (0 == mySignalCounter && myObservers.isEmpty())
    return false;

  if ( myWatchers.isEmpty() )
    return false;

  /* disable watchers one by one */
  int enabled_counter = 0;
  foreach(Watcher* watcher, myWatchers)
  {
    if (watcher && watcher->enable())
    {
      /* item successfully enabled */
      enabled_counter++;
    }
  }

  /* set common enabled flag on only if we have all items enabled */
  myEnabled = (myWatchers.count() == enabled_counter);

  /* function done if no items enabled */
  return (myEnabled);
} /* enable */

bool MemoryNotification :: disable()
{
  if ( !myEnabled )
    return false;

  /* disable watchers one by one */
  int disabled_counter = 0;
  foreach(Watcher* watcher, myWatchers)
  {
    if (watcher && watcher->disable())
    {
      /* item successfully disabled */
      disabled_counter++;
    }
  }

  /* if poller is running - remove it. Likely thread will finished already */
  if ( myPoller )
  {
    myPoller->terminate();
    delete myPoller;
    myPoller = NULL;
  }

  /* set common enabled flag off only if we have all items disabled */
  myEnabled = (myWatchers.count() != disabled_counter);

  /* function done if no items enabled */
  return (! myEnabled);
} /* disable */

bool MemoryNotification :: valid() const
{
  /* first, we must have subscribed items */
  if (0 == mySignalCounter && myObservers.isEmpty())
    return false;

  /* we must have sources for signal generation */
  if ( myWatchers.isEmpty() )
    return false;

  /* All observers must be non-null */
  if ( myObservers.indexOf(NULL) >= 0 )
    return false;

  /* All watchers must be non-null, valid and maybe enabled */
  foreach(const Watcher* watcher, myWatchers)
  {
    if (watcher && watcher->valid() && watcher->enabled() == myEnabled)
    {
      /* check the next item */
      continue;
    }
    return false;
  }

  return true;
} /* valid */

void MemoryNotification :: clearWatchers()
{
  if (myWatchers.count() > 0)
  {
    foreach (Watcher* watcher, myWatchers)
    {
      if (watcher)
        delete watcher;
    }
    myWatchers.clear();
  }
} /* clearWatchers */

void MemoryNotification :: dump() const
{
#if MEMNOTIFY_DUMP
  printf ("MemoryNotification %08x {\n", (uint)this);
  printf ("  ourMemoryNotification %08x signal counter %u enabled %d polling thread %08x\n",
          (uint)ourMemoryNotification, mySignalCounter, myEnabled, (uint)myPoller
      );

  if ( myPoller )
    printf ("  polling is running: %d\n", myPoller->isRunning());

  printf ("  observers %d {\n", myObservers.count());
  foreach (OBSERVER observer, myObservers)
  {
    printf ("\t%08x\n", (uint)observer);
  }
  printf ("  }\n");

  printf ("  watchers %d {\n", myWatchers.count());
  foreach (const Watcher* watcher, myWatchers)
  {
    printf ("\t%08x ", (uint)watcher);
    if (watcher)
      watcher->dump();
    else
      printf ("\n");
  }
  printf ("  }\n");

  printf ("}\n");
#endif /* if MEMNOTIFY_DUMP */
}

END_MEMOTIFY_NAMESPACE

/* =================[ end of file memnotify/memory_notification.cpp ]========================= */
<|endoftext|>


<commit_before>#include <fastrtps/log/Log.h>
#include <fastrtps/log/StdoutConsumer.h>
#include <iostream>

using namespace std;
namespace eprosima {
namespace fastrtps {

struct Log::Resources Log::mResources;

Log::Resources::Resources():
   mDefaultConsumer(new StdoutConsumer),
   mLogging(false),
   mWork(false),
   mFilenames(false),
   mFunctions(true),
   mVerbosity(Log::Error)
{
}

Log::Resources::~Resources()
{
   Log::KillThread();
}

void Log::RegisterConsumer(std::unique_ptr<LogConsumer> consumer)
{
   std::unique_lock<std::mutex> guard(mResources.mConfigMutex);
   mResources.mConsumers.emplace_back(std::move(consumer));
}

void Log::Reset()
{
   std::unique_lock<std::mutex> configGuard(mResources.mConfigMutex);
   mResources.mCategoryFilter.reset();
   mResources.mFilenameFilter.reset();
   mResources.mErrorStringFilter.reset();
   mResources.mFilenames = false;
   mResources.mFunctions = true;
   mResources.mVerbosity = Log::Error;
   mResources.mConsumers.clear();
}

void Log::Run()
{
   std::unique_lock<std::mutex> guard(mResources.mCvMutex);
   while (mResources.mLogging)
   {
      while (mResources.mWork)
      {
         mResources.mWork = false;
         guard.unlock();

         mResources.mLogs.Swap();
         while (!mResources.mLogs.Empty())
         {
            std::unique_lock<std::mutex> configGuard(mResources.mConfigMutex);
            if (Preprocess(mResources.mLogs.Front()))
            {
               for (auto& consumer: mResources.mConsumers)
                  consumer->Consume(mResources.mLogs.Front());

               mResources.mDefaultConsumer->Consume(mResources.mLogs.Front());
            }

            mResources.mLogs.Pop();
         }

         guard.lock();
      }
      if (mResources.mLogging)
         mResources.mCv.wait(guard);
   }
}

void Log::ReportFilenames(bool report)
{
   std::unique_lock<std::mutex> configGuard(mResources.mConfigMutex);
   mResources.mFilenames = report;
}

void Log::ReportFunctions(bool report)
{
   std::unique_lock<std::mutex> configGuard(mResources.mConfigMutex);
   mResources.mFunctions = report;
}

bool Log::Preprocess(Log::Entry& entry)
{
   if (mResources.mCategoryFilter && !regex_search(entry.context.category, *mResources.mCategoryFilter))
      return false;
   if (mResources.mFilenameFilter && !regex_search(entry.context.filename, *mResources.mFilenameFilter))
      return false;
   if (mResources.mErrorStringFilter && !regex_search(entry.message, *mResources.mErrorStringFilter))
      return false;
   if (!mResources.mFilenames)
      entry.context.filename = nullptr;
   if (!mResources.mFunctions)
      entry.context.function = nullptr;

   return true;
}

void Log::KillThread()
{
   {
      std::unique_lock<std::mutex> guard(mResources.mCvMutex);
      mResources.mLogging = false;
      mResources.mWork = false;
   }
   if (mResources.mLoggingThread)
   {
      // The #ifdef workaround here is due to an unsolved MSVC bug, which Microsoft has announced
      // they have no intention of solving: https://connect.microsoft.com/VisualStudio/feedback/details/747145
      // Each VS version deals with post-main deallocation of threads in a very different way.
      #if !defined(_WIN32) || defined(FASTRTPS_STATIC_LINK)
      mResources.mCv.notify_all();
      #if !(defined(_MSC_VER) && _MSC_VER == 1400)
      mResources.mLoggingThread->join();
      #endif
      #endif
      mResources.mLoggingThread.reset();
   }
}

void Log::QueueLog(const std::string& message, const Log::Context& context, Log::Kind kind)
{
   {
      std::unique_lock<std::mutex> guard(mResources.mCvMutex);
      if (!mResources.mLogging && !mResources.mLoggingThread)
      {
         mResources.mLogging = true;
         mResources.mLoggingThread.reset(new thread(Log::Run));
      }
   }

   mResources.mLogs.Push(Log::Entry{message, context, kind});
   {
      std::unique_lock<std::mutex> guard(mResources.mCvMutex);
      mResources.mWork = true;
   }
   mResources.mCv.notify_all();
}

Log::Kind Log::GetVerbosity()
{
   return mResources.mVerbosity;
}

void Log::SetVerbosity(Log::Kind kind)
{
   std::unique_lock<std::mutex> configGuard(mResources.mConfigMutex);
   mResources.mVerbosity = kind;
}

void Log::SetCategoryFilter(const std::regex& filter)
{
   std::unique_lock<std::mutex> configGuard(mResources.mConfigMutex);
   mResources.mCategoryFilter.reset(new std::regex(filter));
}

void Log::SetFilenameFilter(const std::regex& filter)
{
   std::unique_lock<std::mutex> configGuard(mResources.mConfigMutex);
   mResources.mFilenameFilter.reset(new std::regex(filter));
}

void Log::SetErrorStringFilter(const std::regex& filter)
{
   std::unique_lock<std::mutex> configGuard(mResources.mConfigMutex);
   mResources.mErrorStringFilter.reset(new std::regex(filter));
}

} //namespace fastrtps
} //namespace eprosima
<commit_msg>Right visual studio version<commit_after>#include <fastrtps/log/Log.h>
#include <fastrtps/log/StdoutConsumer.h>
#include <iostream>

using namespace std;
namespace eprosima {
namespace fastrtps {

struct Log::Resources Log::mResources;

Log::Resources::Resources():
   mDefaultConsumer(new StdoutConsumer),
   mLogging(false),
   mWork(false),
   mFilenames(false),
   mFunctions(true),
   mVerbosity(Log::Error)
{
}

Log::Resources::~Resources()
{
   Log::KillThread();
}

void Log::RegisterConsumer(std::unique_ptr<LogConsumer> consumer)
{
   std::unique_lock<std::mutex> guard(mResources.mConfigMutex);
   mResources.mConsumers.emplace_back(std::move(consumer));
}

void Log::Reset()
{
   std::unique_lock<std::mutex> configGuard(mResources.mConfigMutex);
   mResources.mCategoryFilter.reset();
   mResources.mFilenameFilter.reset();
   mResources.mErrorStringFilter.reset();
   mResources.mFilenames = false;
   mResources.mFunctions = true;
   mResources.mVerbosity = Log::Error;
   mResources.mConsumers.clear();
}

void Log::Run()
{
   std::unique_lock<std::mutex> guard(mResources.mCvMutex);
   while (mResources.mLogging)
   {
      while (mResources.mWork)
      {
         mResources.mWork = false;
         guard.unlock();

         mResources.mLogs.Swap();
         while (!mResources.mLogs.Empty())
         {
            std::unique_lock<std::mutex> configGuard(mResources.mConfigMutex);
            if (Preprocess(mResources.mLogs.Front()))
            {
               for (auto& consumer: mResources.mConsumers)
                  consumer->Consume(mResources.mLogs.Front());

               mResources.mDefaultConsumer->Consume(mResources.mLogs.Front());
            }

            mResources.mLogs.Pop();
         }

         guard.lock();
      }
      if (mResources.mLogging)
         mResources.mCv.wait(guard);
   }
}

void Log::ReportFilenames(bool report)
{
   std::unique_lock<std::mutex> configGuard(mResources.mConfigMutex);
   mResources.mFilenames = report;
}

void Log::ReportFunctions(bool report)
{
   std::unique_lock<std::mutex> configGuard(mResources.mConfigMutex);
   mResources.mFunctions = report;
}

bool Log::Preprocess(Log::Entry& entry)
{
   if (mResources.mCategoryFilter && !regex_search(entry.context.category, *mResources.mCategoryFilter))
      return false;
   if (mResources.mFilenameFilter && !regex_search(entry.context.filename, *mResources.mFilenameFilter))
      return false;
   if (mResources.mErrorStringFilter && !regex_search(entry.message, *mResources.mErrorStringFilter))
      return false;
   if (!mResources.mFilenames)
      entry.context.filename = nullptr;
   if (!mResources.mFunctions)
      entry.context.function = nullptr;

   return true;
}

void Log::KillThread()
{
   {
      std::unique_lock<std::mutex> guard(mResources.mCvMutex);
      mResources.mLogging = false;
      mResources.mWork = false;
   }
   if (mResources.mLoggingThread)
   {
      // The #ifdef workaround here is due to an unsolved MSVC bug, which Microsoft has announced
      // they have no intention of solving: https://connect.microsoft.com/VisualStudio/feedback/details/747145
      // Each VS version deals with post-main deallocation of threads in a very different way.
      #if !defined(_WIN32) || defined(FASTRTPS_STATIC_LINK)
      mResources.mCv.notify_all();
      #if !(defined(_MSC_VER) && _MSC_VER == 1800)
      mResources.mLoggingThread->join();
      #endif
      #endif
      mResources.mLoggingThread.reset();
   }
}

void Log::QueueLog(const std::string& message, const Log::Context& context, Log::Kind kind)
{
   {
      std::unique_lock<std::mutex> guard(mResources.mCvMutex);
      if (!mResources.mLogging && !mResources.mLoggingThread)
      {
         mResources.mLogging = true;
         mResources.mLoggingThread.reset(new thread(Log::Run));
      }
   }

   mResources.mLogs.Push(Log::Entry{message, context, kind});
   {
      std::unique_lock<std::mutex> guard(mResources.mCvMutex);
      mResources.mWork = true;
   }
   mResources.mCv.notify_all();
}

Log::Kind Log::GetVerbosity()
{
   return mResources.mVerbosity;
}

void Log::SetVerbosity(Log::Kind kind)
{
   std::unique_lock<std::mutex> configGuard(mResources.mConfigMutex);
   mResources.mVerbosity = kind;
}

void Log::SetCategoryFilter(const std::regex& filter)
{
   std::unique_lock<std::mutex> configGuard(mResources.mConfigMutex);
   mResources.mCategoryFilter.reset(new std::regex(filter));
}

void Log::SetFilenameFilter(const std::regex& filter)
{
   std::unique_lock<std::mutex> configGuard(mResources.mConfigMutex);
   mResources.mFilenameFilter.reset(new std::regex(filter));
}

void Log::SetErrorStringFilter(const std::regex& filter)
{
   std::unique_lock<std::mutex> configGuard(mResources.mConfigMutex);
   mResources.mErrorStringFilter.reset(new std::regex(filter));
}

} //namespace fastrtps
} //namespace eprosima
<|endoftext|>


<commit_before>#include <mos/gfx/cube_camera.hpp>
#include <glm/gtc/matrix_transform.hpp>

namespace mos::gfx {

Cube_camera::Cube_camera(const glm::vec3 &position, const float near, const float far) :
    cameras{{Camera(position,
                    position + glm::vec3(1.0f,
                                         0.0f,
                                         0.0f),
                    glm::perspective(glm::half_pi<float>(),
                                     1.0f,
                                     near,
                                     far),
                    glm::vec3(0.0f, -1.0f, 0.0f)),
             Camera(position,
                    position + glm::vec3(-1.0f,
                                         0.0f,
                                         0.0f),
                    cameras[0].projection(),
                    glm::vec3(0.0f, -1.0f, 0.0f)),
             Camera(position,
                    position + glm::vec3(0.0f,
                                         1.0f,
                                         0.0f),
                    cameras[0].projection(),
                    glm::vec3(0.0f, 0.0f, 1.0f)),
             Camera(position,
                    position + glm::vec3(0.0f,
                                         -1.0f,
                                         0.0f),
                    cameras[0].projection(),
                    glm::vec3(0.0f, 0.0f, -1.0f)),
             Camera(position,
                    position + glm::vec3(0.0f,
                                         0.0f,
                                         1.0f),
                    cameras[0].projection(),
                    glm::vec3(0.0f, -1.0f, 0.0f)),
             Camera(position,
                    position + glm::vec3(0.0f,
                                         0.0f,
                                         -1.0f),
                    cameras[0].projection(),
                    glm::vec3(0.0f,
                              -1.0f,
                              0.0f))}} {}
auto Cube_camera::position() const -> glm::vec3 {
  return cameras[0].position();
}

void Cube_camera::position(const glm::vec3 &position) {
  cameras[0].position(position);
  cameras[0].direction(glm::vec3(1.0f, 0.0f, 0.0f));
  cameras[1].position(position);
  cameras[1].direction(glm::vec3(-1.0f, 0.0f, 0.0f));
  cameras[2].position(position);
  cameras[2].direction(glm::vec3(0.0f, 1.0f, 0.0f));
  cameras[3].position(position);
  cameras[3].direction(glm::vec3(0.0f, -1.0f, 0.0f));
  cameras[4].position(position);
  cameras[4].direction(glm::vec3(0.0f, 0.0f, 1.0f));
  cameras[5].position(position);
  cameras[5].direction(glm::vec3(0.0f, 0.0f, -1.0f));
}

void Cube_camera::near_far(const float near, const float far) {
  for (auto &camera : cameras) {
    camera.projection(glm::perspective(glm::half_pi<float>(),
                                         1.0f,
                                         near,
                                         far));
  }
}
}
<commit_msg>Refactor cube camera<commit_after>#include <mos/gfx/cube_camera.hpp>
#include <glm/gtc/matrix_transform.hpp>

namespace mos::gfx {

namespace  {

const glm::vec3 x_axis{1.0f, 0.0f, 1.0f};
const glm::vec3 y_axis{0.0f, 1.0f, 0.0f};
const glm::vec3 z_axis{0.0f, 0.0f, 1.0f};

} // namespace

Cube_camera::Cube_camera(const glm::vec3 &position, const float near,
                         const float far)
    : cameras{
          {Camera(position, position + x_axis,
                  glm::perspective(glm::half_pi<float>(), 1.0f, near, far),
                  -y_axis),
           Camera(position, position - x_axis, cameras[0].projection(),
                  -y_axis),
           Camera(position, position + y_axis, cameras[0].projection(), z_axis),
           Camera(position, position - y_axis, cameras[0].projection(),
                  -z_axis),
           Camera(position, position + z_axis, cameras[0].projection(),
                  -y_axis),
           Camera(position, position - z_axis, cameras[0].projection(),
                  -y_axis)}} {}
auto Cube_camera::position() const -> glm::vec3 {
  return cameras[0].position();
}

void Cube_camera::position(const glm::vec3 &position) {
  cameras[0].position(position);
  cameras[0].direction(x_axis);
  cameras[1].position(position);
  cameras[1].direction(-x_axis);
  cameras[2].position(position);
  cameras[2].direction(y_axis);
  cameras[3].position(position);
  cameras[3].direction(-y_axis);
  cameras[4].position(position);
  cameras[4].direction(z_axis);
  cameras[5].position(position);
  cameras[5].direction(-z_axis);
}

void Cube_camera::near_far(const float near, const float far) {
  for (auto &camera : cameras) {
    camera.projection(glm::perspective(glm::half_pi<float>(), 1.0f, near, far));
  }
}
} // namespace mos::gfx
<|endoftext|>


<commit_before>#include "GG_Clock.h"
#include "PerfTimer.h"

GG_Clock::GG_Clock()
{
	msTimer = new PerfTimer();
	msGameTimer = new PerfTimer();
	fpsTimer = new PerfTimer();
}

GG_Clock::~GG_Clock()
{
	RELEASE(msTimer);
	RELEASE(msGameTimer);
	RELEASE(fpsTimer);
}

/**
*	- OnPrepareUpdate: Calculate all attributes at the begging of each frame
*		- Add the elapsed time.
*		- Recal real dt.
*		- Add one frame to counter.
*		- If app state is PLAY do the same with the game timer.
*/
void GG_Clock::OnPrepareUpdate(APP_STATE appState)
{
	//1. Add time
	timeSinceAppStart += realDt;
	timeSinceLevelLoaded += realDt;
	//2. Calc dt
	realDt = (float)(msTimer->ReadMs() / 1000.0f);
	if (realDt > maximumDT) realDt = 1 / 30.0f;
	msTimer->Start();
	//3. Add a frame
	++realFrameCount;

	if (appState == APP_STATE::PLAY)
	{
		gameTimeSinceLevelLoaded += gameDt;

		gameDt = ((float)(msGameTimer->ReadMs() / 1000.0f)) * scale;
		msGameTimer->Start();

		++gameFrameCount;
	}
}

/**
*	- OnFinishUpdate: Calculate all attributes at the ending of the frame.
*		- Add one to fps counter.
*		- Check if one second has passed to calculate fps.
*		- Calculate last frame ms.
*/
void GG_Clock::OnFinishUpdate()
{
	++fpsCounter;

	if (fpsTimer->ReadMs() > 1000.0f)
	{
		lastFps = fpsCounter;
		fpsCounter = 0;
		fpsTimer->Start();
	}

	lastFrameMs = msTimer->ReadMs();
}

void GG_Clock::OnSceneLoaded()
{
	timeSinceLevelLoaded = 0.0;
}

void GG_Clock::Pause()
{
	msGameTimer->Stop();
}

void GG_Clock::UnPause()
{
	msGameTimer->Start();
}

void GG_Clock::Stop()
{
	msGameTimer->Stop();
	gameFrameCount = 0;
	gameDt = 0.0f;
}

void GG_Clock::Play()
{
	msGameTimer->Start();
}

/**
*	- DT: Return real dt.
*/
float GG_Clock::DT() const
{
	return realDt;
}

/**
*	- RealFrameCount: Return the real frames passed.
*/
uint GG_Clock::RealFrameCount() const
{
	return realFrameCount;
}

/**
*	- FPS: Return the fps counter.
*/
uint GG_Clock::FPS() const
{
	return fpsCounter;
}

/**
*	- LastFPS: Return the last frame fps counter.
*/
uint GG_Clock::LastFPS() const
{
	return lastFps;
}

/**
*	- TimeSinceStart: Return the time in seconds since app started.
*/
float GG_Clock::TimeSinceStart() const
{
	return timeSinceAppStart;
}

/**
*	- TimeSinceSceneLoaded: Return the time in seconds since scene was loaded.
*/
float GG_Clock::TimeSinceSceneLoaded() const
{
	return timeSinceLevelLoaded;
}

/**
*	- GameDT: Return the game dt.
*/
float GG_Clock::GameDT() const
{
	return gameDt;
}

/**
*	- GameFrameCounter: Return the game frames passed.
*/
uint GG_Clock::GameFrameCounter() const
{
	return gameFrameCount;
}

/**
*	- TimeSinceSceneLoaded: Return the time in seconds since scene was loaded in game scale.
*/
float GG_Clock::GameTimeSinceLevelLoaded() const
{
	return gameTimeSinceLevelLoaded;
}

/**
*	- GetScale: Return the game time scale.
*/
float GG_Clock::GetScale() const
{
	return scale;
}

/**
*	- LastFrameMs: Return the last frame ms.
*/
float GG_Clock::LastFrameMs() const
{
	return lastFrameMs;
}

/**
*	- SetScale: Set the game time scale.
*/
void GG_Clock::SetScale(float scl)
{
	if (scl >= 0.0f)
		scale = scl;
	else
		scale = 0.0f;
}
<commit_msg>Not stopping the game clock on pause<commit_after>#include "GG_Clock.h"
#include "PerfTimer.h"

GG_Clock::GG_Clock()
{
	msTimer = new PerfTimer();
	msGameTimer = new PerfTimer();
	fpsTimer = new PerfTimer();
}

GG_Clock::~GG_Clock()
{
	RELEASE(msTimer);
	RELEASE(msGameTimer);
	RELEASE(fpsTimer);
}

/**
*	- OnPrepareUpdate: Calculate all attributes at the begging of each frame
*		- Add the elapsed time.
*		- Recal real dt.
*		- Add one frame to counter.
*		- If app state is PLAY do the same with the game timer.
*/
void GG_Clock::OnPrepareUpdate(APP_STATE appState)
{
	//1. Add time
	timeSinceAppStart += realDt;
	timeSinceLevelLoaded += realDt;
	//2. Calc dt
	realDt = (float)(msTimer->ReadMs() / 1000.0f);
	if (realDt > maximumDT) realDt = 1 / 30.0f;
	msTimer->Start();
	//3. Add a frame
	++realFrameCount;

	if (appState == APP_STATE::PLAY)
	{
		gameTimeSinceLevelLoaded += gameDt;

		gameDt = ((float)(msGameTimer->ReadMs() / 1000.0f)) * scale;
		msGameTimer->Start();

		++gameFrameCount;
	}
}

/**
*	- OnFinishUpdate: Calculate all attributes at the ending of the frame.
*		- Add one to fps counter.
*		- Check if one second has passed to calculate fps.
*		- Calculate last frame ms.
*/
void GG_Clock::OnFinishUpdate()
{
	++fpsCounter;

	if (fpsTimer->ReadMs() > 1000.0f)
	{
		lastFps = fpsCounter;
		fpsCounter = 0;
		fpsTimer->Start();
	}

	lastFrameMs = msTimer->ReadMs();
}

void GG_Clock::OnSceneLoaded()
{
	timeSinceLevelLoaded = 0.0;
}

void GG_Clock::Pause()
{
	//TODO: Check this, make sense to stop the time even if u pause?? (Scene since level started should continue even if u pause)
	//msGameTimer->Stop();
}

void GG_Clock::UnPause()
{
	msGameTimer->Start();
}

void GG_Clock::Stop()
{
	msGameTimer->Stop();
	gameFrameCount = 0;
	gameDt = 0.0f;
}

void GG_Clock::Play()
{
	msGameTimer->Start();
}

/**
*	- DT: Return real dt.
*/
float GG_Clock::DT() const
{
	return realDt;
}

/**
*	- RealFrameCount: Return the real frames passed.
*/
uint GG_Clock::RealFrameCount() const
{
	return realFrameCount;
}

/**
*	- FPS: Return the fps counter.
*/
uint GG_Clock::FPS() const
{
	return fpsCounter;
}

/**
*	- LastFPS: Return the last frame fps counter.
*/
uint GG_Clock::LastFPS() const
{
	return lastFps;
}

/**
*	- TimeSinceStart: Return the time in seconds since app started.
*/
float GG_Clock::TimeSinceStart() const
{
	return timeSinceAppStart;
}

/**
*	- TimeSinceSceneLoaded: Return the time in seconds since scene was loaded.
*/
float GG_Clock::TimeSinceSceneLoaded() const
{
	return timeSinceLevelLoaded;
}

/**
*	- GameDT: Return the game dt.
*/
float GG_Clock::GameDT() const
{
	return gameDt;
}

/**
*	- GameFrameCounter: Return the game frames passed.
*/
uint GG_Clock::GameFrameCounter() const
{
	return gameFrameCount;
}

/**
*	- TimeSinceSceneLoaded: Return the time in seconds since scene was loaded in game scale.
*/
float GG_Clock::GameTimeSinceLevelLoaded() const
{
	return gameTimeSinceLevelLoaded;
}

/**
*	- GetScale: Return the game time scale.
*/
float GG_Clock::GetScale() const
{
	return scale;
}

/**
*	- LastFrameMs: Return the last frame ms.
*/
float GG_Clock::LastFrameMs() const
{
	return lastFrameMs;
}

/**
*	- SetScale: Set the game time scale.
*/
void GG_Clock::SetScale(float scl)
{
	if (scl >= 0.0f)
		scale = scl;
	else
		scale = 0.0f;
}
<|endoftext|>


<commit_before>//===-- OProfileJITEventListener.cpp - Tell OProfile about JITted code ----===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines a JITEventListener object that calls into OProfile to tell
// it about JITted functions.  For now, we only record function names and sizes,
// but eventually we'll also record line number information.
//
// See http://oprofile.sourceforge.net/doc/devel/jit-interface.html for the
// definition of the interface we're using.
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "oprofile-jit-event-listener"
#include "llvm/Function.h"
#include "llvm/Analysis/DebugInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/ExecutionEngine/JITEventListener.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/System/Errno.h"
#include "llvm/Config/config.h"
#include <stddef.h>
using namespace llvm;

#if USE_OPROFILE

#include <opagent.h>

namespace {

class OProfileJITEventListener : public JITEventListener {
  op_agent_t Agent;
public:
  OProfileJITEventListener();
  ~OProfileJITEventListener();

  virtual void NotifyFunctionEmitted(const Function &F,
                                     void *FnStart, size_t FnSize,
                                     const EmittedFunctionDetails &Details);
  virtual void NotifyFreeingMachineCode(const Function &F, void *OldPtr);
};

OProfileJITEventListener::OProfileJITEventListener()
    : Agent(op_open_agent()) {
  if (Agent == NULL) {
    const std::string err_str = sys::StrError();
    DEBUG(errs() << "Failed to connect to OProfile agent: " << err_str << "\n");
  } else {
    DEBUG(errs() << "Connected to OProfile agent.\n");
  }
}

OProfileJITEventListener::~OProfileJITEventListener() {
  if (Agent != NULL) {
    if (op_close_agent(Agent) == -1) {
      const std::string err_str = sys::StrError();
      DEBUG(errs() << "Failed to disconnect from OProfile agent: "
                   << err_str << "\n");
    } else {
      DEBUG(errs() << "Disconnected from OProfile agent.\n");
    }
  }
}

class FilenameCache {
  // Holds the filename of each Scope, so that we can pass the
  // pointer into oprofile.  These char*s are freed in the destructor.
  DenseMap<MDNode*, char*> Filenames;

 public:
  const char *getFilename(MDNode *Scope) {
    char *&Filename = Filenames[Scope];
    if (Filename == NULL) {
      DIScope S(Scope);
      Filename = strdup(S.getFilename());
    }
    return Filename;
  }
  ~FilenameCache() {
    for (DenseMap<MDNode*, char*>::iterator
             I = Filenames.begin(), E = Filenames.end(); I != E; ++I) {
      free(I->second);
    }
  }
};

static debug_line_info LineStartToOProfileFormat(
    const MachineFunction &MF, FilenameCache &Filenames,
    uintptr_t Address, DebugLoc Loc) {
  debug_line_info Result;
  Result.vma = Address;
  const DebugLocTuple &tuple = MF.getDebugLocTuple(Loc);
  Result.lineno = tuple.Line;
  Result.filename = Filenames.getFilename(tuple.Scope);
  DEBUG(errs() << "Mapping " << reinterpret_cast<void*>(Result.vma) << " to "
               << Result.filename << ":" << Result.lineno << "\n");
  return Result;
}

// Adds the just-emitted function to the symbol table.
void OProfileJITEventListener::NotifyFunctionEmitted(
    const Function &F, void *FnStart, size_t FnSize,
    const EmittedFunctionDetails &Details) {
  assert(F.hasName() && FnStart != 0 && "Bad symbol to add");
  if (op_write_native_code(Agent, F.getName().data(),
                           reinterpret_cast<uint64_t>(FnStart),
                           FnStart, FnSize) == -1) {
    DEBUG(errs() << "Failed to tell OProfile about native function "
          << F.getName() << " at ["
          << FnStart << "-" << ((char*)FnStart + FnSize) << "]\n");
    return;
  }

  // Now we convert the line number information from the address/DebugLoc format
  // in Details to the address/filename/lineno format that OProfile expects.
  // OProfile 0.9.4 (and maybe later versions) has a bug that causes it to
  // ignore line numbers for addresses above 4G.
  FilenameCache Filenames;
  std::vector<debug_line_info> LineInfo;
  LineInfo.reserve(1 + Details.LineStarts.size());
  if (!Details.MF->getDefaultDebugLoc().isUnknown()) {
    LineInfo.push_back(LineStartToOProfileFormat(
        *Details.MF, Filenames,
        reinterpret_cast<uintptr_t>(FnStart),
        Details.MF->getDefaultDebugLoc()));
  }
  for (std::vector<EmittedFunctionDetails::LineStart>::const_iterator
           I = Details.LineStarts.begin(), E = Details.LineStarts.end();
       I != E; ++I) {
    LineInfo.push_back(LineStartToOProfileFormat(
        *Details.MF, Filenames, I->Address, I->Loc));
  }
  if (!LineInfo.empty()) {
    if (op_write_debug_line_info(Agent, FnStart,
                                 LineInfo.size(), &*LineInfo.begin()) == -1) {
      DEBUG(errs()
            << "Failed to tell OProfile about line numbers for native function "
            << F.getName() << " at ["
            << FnStart << "-" << ((char*)FnStart + FnSize) << "]\n");
    }
  }
}

// Removes the being-deleted function from the symbol table.
void OProfileJITEventListener::NotifyFreeingMachineCode(void *FnStart) {
  assert(FnStart && "Invalid function pointer");
  if (op_unload_native_code(Agent, reinterpret_cast<uint64_t>(FnStart)) == -1) {
    DEBUG(errs()
          << "Failed to tell OProfile about unload of native function at "
          << FnStart << "\n");
  }
}

}  // anonymous namespace.

namespace llvm {
JITEventListener *createOProfileJITEventListener() {
  return new OProfileJITEventListener;
}
}

#else  // USE_OPROFILE

namespace llvm {
// By defining this to return NULL, we can let clients call it unconditionally,
// even if they haven't configured with the OProfile libraries.
JITEventListener *createOProfileJITEventListener() {
  return NULL;
}
}  // namespace llvm

#endif  // USE_OPROFILE
<commit_msg>Fix OProfileJITEventListener after r85182.<commit_after>//===-- OProfileJITEventListener.cpp - Tell OProfile about JITted code ----===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines a JITEventListener object that calls into OProfile to tell
// it about JITted functions.  For now, we only record function names and sizes,
// but eventually we'll also record line number information.
//
// See http://oprofile.sourceforge.net/doc/devel/jit-interface.html for the
// definition of the interface we're using.
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "oprofile-jit-event-listener"
#include "llvm/Function.h"
#include "llvm/Analysis/DebugInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/ExecutionEngine/JITEventListener.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/System/Errno.h"
#include "llvm/Config/config.h"
#include <stddef.h>
using namespace llvm;

#if USE_OPROFILE

#include <opagent.h>

namespace {

class OProfileJITEventListener : public JITEventListener {
  op_agent_t Agent;
public:
  OProfileJITEventListener();
  ~OProfileJITEventListener();

  virtual void NotifyFunctionEmitted(const Function &F,
                                     void *FnStart, size_t FnSize,
                                     const EmittedFunctionDetails &Details);
  virtual void NotifyFreeingMachineCode(void *OldPtr);
};

OProfileJITEventListener::OProfileJITEventListener()
    : Agent(op_open_agent()) {
  if (Agent == NULL) {
    const std::string err_str = sys::StrError();
    DEBUG(errs() << "Failed to connect to OProfile agent: " << err_str << "\n");
  } else {
    DEBUG(errs() << "Connected to OProfile agent.\n");
  }
}

OProfileJITEventListener::~OProfileJITEventListener() {
  if (Agent != NULL) {
    if (op_close_agent(Agent) == -1) {
      const std::string err_str = sys::StrError();
      DEBUG(errs() << "Failed to disconnect from OProfile agent: "
                   << err_str << "\n");
    } else {
      DEBUG(errs() << "Disconnected from OProfile agent.\n");
    }
  }
}

class FilenameCache {
  // Holds the filename of each Scope, so that we can pass the
  // pointer into oprofile.  These char*s are freed in the destructor.
  DenseMap<MDNode*, char*> Filenames;

 public:
  const char *getFilename(MDNode *Scope) {
    char *&Filename = Filenames[Scope];
    if (Filename == NULL) {
      DIScope S(Scope);
      Filename = strdup(S.getFilename());
    }
    return Filename;
  }
  ~FilenameCache() {
    for (DenseMap<MDNode*, char*>::iterator
             I = Filenames.begin(), E = Filenames.end(); I != E; ++I) {
      free(I->second);
    }
  }
};

static debug_line_info LineStartToOProfileFormat(
    const MachineFunction &MF, FilenameCache &Filenames,
    uintptr_t Address, DebugLoc Loc) {
  debug_line_info Result;
  Result.vma = Address;
  const DebugLocTuple &tuple = MF.getDebugLocTuple(Loc);
  Result.lineno = tuple.Line;
  Result.filename = Filenames.getFilename(tuple.Scope);
  DEBUG(errs() << "Mapping " << reinterpret_cast<void*>(Result.vma) << " to "
               << Result.filename << ":" << Result.lineno << "\n");
  return Result;
}

// Adds the just-emitted function to the symbol table.
void OProfileJITEventListener::NotifyFunctionEmitted(
    const Function &F, void *FnStart, size_t FnSize,
    const EmittedFunctionDetails &Details) {
  assert(F.hasName() && FnStart != 0 && "Bad symbol to add");
  if (op_write_native_code(Agent, F.getName().data(),
                           reinterpret_cast<uint64_t>(FnStart),
                           FnStart, FnSize) == -1) {
    DEBUG(errs() << "Failed to tell OProfile about native function "
          << F.getName() << " at ["
          << FnStart << "-" << ((char*)FnStart + FnSize) << "]\n");
    return;
  }

  // Now we convert the line number information from the address/DebugLoc format
  // in Details to the address/filename/lineno format that OProfile expects.
  // OProfile 0.9.4 (and maybe later versions) has a bug that causes it to
  // ignore line numbers for addresses above 4G.
  FilenameCache Filenames;
  std::vector<debug_line_info> LineInfo;
  LineInfo.reserve(1 + Details.LineStarts.size());
  if (!Details.MF->getDefaultDebugLoc().isUnknown()) {
    LineInfo.push_back(LineStartToOProfileFormat(
        *Details.MF, Filenames,
        reinterpret_cast<uintptr_t>(FnStart),
        Details.MF->getDefaultDebugLoc()));
  }
  for (std::vector<EmittedFunctionDetails::LineStart>::const_iterator
           I = Details.LineStarts.begin(), E = Details.LineStarts.end();
       I != E; ++I) {
    LineInfo.push_back(LineStartToOProfileFormat(
        *Details.MF, Filenames, I->Address, I->Loc));
  }
  if (!LineInfo.empty()) {
    if (op_write_debug_line_info(Agent, FnStart,
                                 LineInfo.size(), &*LineInfo.begin()) == -1) {
      DEBUG(errs()
            << "Failed to tell OProfile about line numbers for native function "
            << F.getName() << " at ["
            << FnStart << "-" << ((char*)FnStart + FnSize) << "]\n");
    }
  }
}

// Removes the being-deleted function from the symbol table.
void OProfileJITEventListener::NotifyFreeingMachineCode(void *FnStart) {
  assert(FnStart && "Invalid function pointer");
  if (op_unload_native_code(Agent, reinterpret_cast<uint64_t>(FnStart)) == -1) {
    DEBUG(errs()
          << "Failed to tell OProfile about unload of native function at "
          << FnStart << "\n");
  }
}

}  // anonymous namespace.

namespace llvm {
JITEventListener *createOProfileJITEventListener() {
  return new OProfileJITEventListener;
}
}

#else  // USE_OPROFILE

namespace llvm {
// By defining this to return NULL, we can let clients call it unconditionally,
// even if they haven't configured with the OProfile libraries.
JITEventListener *createOProfileJITEventListener() {
  return NULL;
}
}  // namespace llvm

#endif  // USE_OPROFILE
<|endoftext|>


<commit_before>/*******************************************************************************
    Copyright (c) The Taichi Authors (2016- ). All Rights Reserved.
    The use of this software is governed by the LICENSE file.
*******************************************************************************/

#include <taichi/system/threading.h>

TC_NAMESPACE_BEGIN

class ThreadPool {
public:
  ThreadPool() {
    TC_TAG;
  }
};

bool test_threading() {
  auto tp = ThreadPool();
  return true;
}

TC_NAMESPACE_END
<commit_msg>thread pool base<commit_after>/*******************************************************************************
    Copyright (c) The Taichi Authors (2016- ). All Rights Reserved.
    The use of this software is governed by the LICENSE file.
*******************************************************************************/

#include <taichi/system/threading.h>
#include <thread>
#include <condition_variable>

TC_NAMESPACE_BEGIN

class ThreadPool {
public:
  std::vector<std::thread> threads;
  std::condition_variable cv;
  std::mutex mutex;
  bool running;
  bool finished;

  void task() {
    while (true) {
      std::unique_lock<std::mutex> lock(mutex);
      cv.wait(lock, [this]{ return running;});
      if (finished) {
        break;
      }
      TC_TAG;
    }
  }

  ThreadPool(int num_threads) {
    running = false;
    finished = false;
    threads.resize((std::size_t)num_threads);
    for (int i = 0; i < num_threads; i++) {
      threads[i] = std::thread([this] {
        this->task();
      });
    }
  }

  void start() {
    {
      std::lock_guard<std::mutex> lg(mutex);
      running = true;
    }
    cv.notify_all();
  }

  ~ThreadPool() {
    {
      std::lock_guard<std::mutex> lg(mutex);
      finished = true;
    }
    cv.notify_all();
    for (int i = 0; i < threads.size(); i++) {
      threads[i].join();
    }
  }
};

bool test_threading() {
  auto tp = ThreadPool(4);
  tp.start();
  return true;
}

TC_NAMESPACE_END
<|endoftext|>


<commit_before>///////////////////////////////////////////////////////////////////////////////////
/// OpenGL Mathematics (glm.g-truc.net)
///
/// Copyright (c) 2005 - 2011 G-Truc Creation (www.g-truc.net)
/// 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.
///
/// @ref core
/// @file glm/core/func_packing.inl
/// @date 2010-03-17 / 2011-06-15
/// @author Christophe Riccio
///////////////////////////////////////////////////////////////////////////////////

namespace glm
{
	GLM_FUNC_QUALIFIER detail::uint32 packUnorm2x16(detail::tvec2<detail::float32> const & v)
	{
		detail::uint16 A(detail::uint16(round(clamp(v.x, 0.0f, 1.0f) * 65535.0f)));
		detail::uint16 B(detail::uint16(round(clamp(v.y, 0.0f, 1.0f) * 65535.0f)));
		return detail::uint32((B << 16) | A);
	}

	GLM_FUNC_QUALIFIER detail::tvec2<detail::float32> unpackUnorm2x16(detail::uint32 const & p)
	{
		detail::uint32 Mask16((1 << 16) - 1);
		detail::uint32 A((p >>  0) & Mask16);
		detail::uint32 B((p >> 16) & Mask16);
		return detail::tvec2<detail::float32>(
			A * 1.0f / 65535.0f,
			B * 1.0f / 65535.0f);
	}

	GLM_FUNC_QUALIFIER detail::uint32 packSnorm2x16(detail::tvec2<detail::float32> const & v)
	{
		union iu
		{
			detail::int16 i;
			detail::uint16 u;
		} A, B;

		detail::tvec2<detail::float32> Unpack = clamp(v ,-1.0f, 1.0f) * 32767.0f;
		A.i = detail::int16(round(Unpack.x));
		B.i = detail::int16(round(Unpack.y));
		detail::uint32 Pack = (detail::uint32(B.u) << 16) | (detail::uint32(A.u) << 0);
		return Pack;
	}

	GLM_FUNC_QUALIFIER detail::tvec2<detail::float32> unpackSnorm2x16(detail::uint32 const & p)
	{
		union iu
		{
			detail::int16 i;
			detail::uint16 u;
		} A, B;

		detail::uint32 Mask16((1 << 16) - 1);
		A.u = detail::uint16((p >>  0) & Mask16);
		B.u = detail::uint16((p >> 16) & Mask16);
		detail::tvec2<detail::float32> Pack(A.i, B.i);

		return clamp(Pack * 1.0f / 32767.0f, -1.0f, 1.0f);
	}

	GLM_FUNC_QUALIFIER detail::uint32 packUnorm4x8(detail::tvec4<detail::float32> const & v)
	{
		detail::uint8 A((detail::uint8)round(clamp(v.x, 0.0f, 1.0f) * 255.0f));
		detail::uint8 B((detail::uint8)round(clamp(v.y, 0.0f, 1.0f) * 255.0f));
		detail::uint8 C((detail::uint8)round(clamp(v.z, 0.0f, 1.0f) * 255.0f));
		detail::uint8 D((detail::uint8)round(clamp(v.w, 0.0f, 1.0f) * 255.0f));
		return detail::uint32((D << 24) | (C << 16) | (B << 8) | A);
	}

	GLM_FUNC_QUALIFIER detail::tvec4<detail::float32> unpackUnorm4x8(detail::uint32 const & p)
	{
		detail::uint32 Mask8((1 << 8) - 1);
		detail::uint32 A((p >>  0) & Mask8);
		detail::uint32 B((p >>  8) & Mask8);
		detail::uint32 C((p >> 16) & Mask8);
		detail::uint32 D((p >> 24) & Mask8);
		return detail::tvec4<detail::float32>(
			A * 1.0f / 255.0f,
			B * 1.0f / 255.0f,
			C * 1.0f / 255.0f,
			D * 1.0f / 255.0f);
	}

	GLM_FUNC_QUALIFIER detail::uint32 packSnorm4x8(detail::tvec4<detail::float32> const & v)
	{
		union iu
		{
			detail::int8 i;
			detail::uint8 u;
		} A, B, C, D;

		detail::tvec4<detail::float32> Unpack = clamp(v ,-1.0f, 1.0f) * 127.0f;
		A.i = detail::int8(round(Unpack.x));
		B.i = detail::int8(round(Unpack.y));
		C.i = detail::int8(round(Unpack.z));
		D.i = detail::int8(round(Unpack.w));
		detail::uint32 Pack = (detail::uint32(D.u) << 24) | (detail::uint32(C.u) << 16) | (detail::uint32(B.u) << 8) | (detail::uint32(A.u) << 0);
		return Pack;
	}

	GLM_FUNC_QUALIFIER detail::tvec4<detail::float32> unpackSnorm4x8(detail::uint32 const & p)
	{
		union iu
		{
			detail::int8 i;
			detail::uint8 u;
		} A, B, C, D;

		detail::uint32 Mask8((1 << 8) - 1);
		A.u = detail::uint8((p >>  0) & Mask8);
		B.u = detail::uint8((p >>  8) & Mask8);
		C.u = detail::uint8((p >> 16) & Mask8);
		D.u = detail::uint8((p >> 24) & Mask8);
		detail::tvec4<detail::float32> Pack(A.i, B.i, C.i, D.i);

		return clamp(Pack * 1.0f / 127.0f, -1.0f, 1.0f);
	}

	GLM_FUNC_QUALIFIER double packDouble2x32(detail::tvec2<detail::uint32> const & v)
	{
		return *(double*)&v;
	}

	GLM_FUNC_QUALIFIER detail::tvec2<uint> unpackDouble2x32(double const & v)
	{
		return *(detail::tvec2<uint>*)&v;
	}

	GLM_FUNC_QUALIFIER uint packHalf2x16(detail::tvec2<float> const & v)
	{
		detail::tvec2<detail::hdata> Pack(detail::toFloat16(v.x), detail::toFloat16(v.y));
		return *(uint*)&Pack;
	}

	GLM_FUNC_QUALIFIER vec2 unpackHalf2x16(uint const & v)
	{
		detail::tvec2<detail::hdata> Unpack = *(detail::tvec2<detail::hdata>*)&v;
		return vec2(detail::toFloat32(Unpack.x), detail::toFloat32(Unpack.y));
	}
}//namespace glm
<commit_msg>Fixed ticket #141, strict aliasing warning<commit_after>///////////////////////////////////////////////////////////////////////////////////
/// OpenGL Mathematics (glm.g-truc.net)
///
/// Copyright (c) 2005 - 2011 G-Truc Creation (www.g-truc.net)
/// 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.
///
/// @ref core
/// @file glm/core/func_packing.inl
/// @date 2010-03-17 / 2011-06-15
/// @author Christophe Riccio
///////////////////////////////////////////////////////////////////////////////////

namespace glm
{
	GLM_FUNC_QUALIFIER detail::uint32 packUnorm2x16(detail::tvec2<detail::float32> const & v)
	{
		detail::uint16 A(detail::uint16(round(clamp(v.x, 0.0f, 1.0f) * 65535.0f)));
		detail::uint16 B(detail::uint16(round(clamp(v.y, 0.0f, 1.0f) * 65535.0f)));
		return detail::uint32((B << 16) | A);
	}

	GLM_FUNC_QUALIFIER detail::tvec2<detail::float32> unpackUnorm2x16(detail::uint32 const & p)
	{
		detail::uint32 Mask16((1 << 16) - 1);
		detail::uint32 A((p >>  0) & Mask16);
		detail::uint32 B((p >> 16) & Mask16);
		return detail::tvec2<detail::float32>(
			A * 1.0f / 65535.0f,
			B * 1.0f / 65535.0f);
	}

	GLM_FUNC_QUALIFIER detail::uint32 packSnorm2x16(detail::tvec2<detail::float32> const & v)
	{
		union iu
		{
			detail::int16 i;
			detail::uint16 u;
		} A, B;

		detail::tvec2<detail::float32> Unpack = clamp(v ,-1.0f, 1.0f) * 32767.0f;
		A.i = detail::int16(round(Unpack.x));
		B.i = detail::int16(round(Unpack.y));
		detail::uint32 Pack = (detail::uint32(B.u) << 16) | (detail::uint32(A.u) << 0);
		return Pack;
	}

	GLM_FUNC_QUALIFIER detail::tvec2<detail::float32> unpackSnorm2x16(detail::uint32 const & p)
	{
		union iu
		{
			detail::int16 i;
			detail::uint16 u;
		} A, B;

		detail::uint32 Mask16((1 << 16) - 1);
		A.u = detail::uint16((p >>  0) & Mask16);
		B.u = detail::uint16((p >> 16) & Mask16);
		detail::tvec2<detail::float32> Pack(A.i, B.i);

		return clamp(Pack * 1.0f / 32767.0f, -1.0f, 1.0f);
	}

	GLM_FUNC_QUALIFIER detail::uint32 packUnorm4x8(detail::tvec4<detail::float32> const & v)
	{
		detail::uint8 A((detail::uint8)round(clamp(v.x, 0.0f, 1.0f) * 255.0f));
		detail::uint8 B((detail::uint8)round(clamp(v.y, 0.0f, 1.0f) * 255.0f));
		detail::uint8 C((detail::uint8)round(clamp(v.z, 0.0f, 1.0f) * 255.0f));
		detail::uint8 D((detail::uint8)round(clamp(v.w, 0.0f, 1.0f) * 255.0f));
		return detail::uint32((D << 24) | (C << 16) | (B << 8) | A);
	}

	GLM_FUNC_QUALIFIER detail::tvec4<detail::float32> unpackUnorm4x8(detail::uint32 const & p)
	{
		detail::uint32 Mask8((1 << 8) - 1);
		detail::uint32 A((p >>  0) & Mask8);
		detail::uint32 B((p >>  8) & Mask8);
		detail::uint32 C((p >> 16) & Mask8);
		detail::uint32 D((p >> 24) & Mask8);
		return detail::tvec4<detail::float32>(
			A * 1.0f / 255.0f,
			B * 1.0f / 255.0f,
			C * 1.0f / 255.0f,
			D * 1.0f / 255.0f);
	}

	GLM_FUNC_QUALIFIER detail::uint32 packSnorm4x8(detail::tvec4<detail::float32> const & v)
	{
		union iu
		{
			detail::int8 i;
			detail::uint8 u;
		} A, B, C, D;

		detail::tvec4<detail::float32> Unpack = clamp(v ,-1.0f, 1.0f) * 127.0f;
		A.i = detail::int8(round(Unpack.x));
		B.i = detail::int8(round(Unpack.y));
		C.i = detail::int8(round(Unpack.z));
		D.i = detail::int8(round(Unpack.w));
		detail::uint32 Pack = (detail::uint32(D.u) << 24) | (detail::uint32(C.u) << 16) | (detail::uint32(B.u) << 8) | (detail::uint32(A.u) << 0);
		return Pack;
	}

	GLM_FUNC_QUALIFIER detail::tvec4<detail::float32> unpackSnorm4x8(detail::uint32 const & p)
	{
		union iu
		{
			detail::int8 i;
			detail::uint8 u;
		} A, B, C, D;

		detail::uint32 Mask8((1 << 8) - 1);
		A.u = detail::uint8((p >>  0) & Mask8);
		B.u = detail::uint8((p >>  8) & Mask8);
		C.u = detail::uint8((p >> 16) & Mask8);
		D.u = detail::uint8((p >> 24) & Mask8);
		detail::tvec4<detail::float32> Pack(A.i, B.i, C.i, D.i);

		return clamp(Pack * 1.0f / 127.0f, -1.0f, 1.0f);
	}

	GLM_FUNC_QUALIFIER double packDouble2x32(detail::tvec2<detail::uint32> const & v)
	{
		return *(double*)&v;
	}

	GLM_FUNC_QUALIFIER detail::tvec2<uint> unpackDouble2x32(double const & v)
	{
		return *(detail::tvec2<uint>*)&v;
	}

	GLM_FUNC_QUALIFIER uint packHalf2x16(detail::tvec2<float> const & v)
	{
        union helper
        {
            uint other;
            struct
            {
                detail::hdata a, b;
            } orig;
        } Pack;

        Pack.orig.a = detail::toFloat16(v.x);
        Pack.orig.b = detail::toFloat16(v.y);
		return *(uint*)&Pack;
	}

	GLM_FUNC_QUALIFIER vec2 unpackHalf2x16(uint const & v)
	{
        union helper
        {
            uint other;
            struct
            {
                detail::hdata a, b;
            } orig;
        } Unpack;
        Unpack.other = v;

		return vec2(detail::toFloat32(Unpack.orig.a), detail::toFloat32(Unpack.orig.b));
	}
}//namespace glm

<|endoftext|>