<commit_before>/*
 * Copyright 2009-2019 The VOTCA Development Team (http://www.votca.org)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

#include "csg_imc_solve.h"
#include <fstream>
#include <votca/tools/table.h>

int main(int argc, char** argv) {
  CG_IMC_solve app;
  return app.Exec(argc, argv);
}

void CG_IMC_solve::Initialize(void) {
  namespace propt = boost::program_options;

  AddProgramOptions()("regularization,r",
                      propt::value<double>()->default_value(0.0),
                      "regularization factor");

  AddProgramOptions()("imcfile,i", boost::program_options::value<std::string>(),
                      "imc statefile");

  AddProgramOptions()("gmcfile,g", boost::program_options::value<std::string>(),
                      "gmc statefile");

  AddProgramOptions()("outputfile,o",
                      boost::program_options::value<std::string>(),
                      "outputfile");
}

bool CG_IMC_solve::EvaluateOptions() {
  CheckRequired("imcfile", "Missing imcfile");
  CheckRequired("gmcfile", "Missing gmcfile");
  CheckRequired("outputfile", "Missing outputfile");
  return true;
}

Eigen::MatrixXd CG_IMC_solve::LoadMatrix(const std::string& filename) const {
  std::ifstream intt;
  intt.open(filename);
  if (!intt)
    throw std::runtime_error(std::string("error, cannot open file ") +
                             filename);

  std::string line;
  std::vector<double> result;
  int numrows = 0;
  int numcols = 0;
  while (getline(intt, line)) {
    if (line[0] == '#') {
      continue;
    }
    votca::tools::Tokenizer tok(line, " \t");
    std::vector<std::string> tokens = tok.ToVector();
    if (numrows == 0) {
      numcols = tokens.size();
    } else if (numcols != tokens.size()) {
      throw std::runtime_error(
          "Matrix has not the same number of entries in each row.");
    }
    for (const std::string& s : tokens) {
      result.push_back(std::stod(tokens[0]));
    }
    numrows++;
  }
  intt.close();

  return Eigen::Map<Eigen::MatrixXd>(result.data(), numrows, numcols);
}

void CG_IMC_solve::Run() {
  std::string imcfile = _op_vm["imcfile"].as<std::string>();
  std::string gmcfile = _op_vm["gmcfile"].as<std::string>();
  std::string outputfile = _op_vm["outputfile"].as<std::string>();

  double reg = _op_vm["regularization"].as<double>();

  Eigen::MatrixXd A = LoadMatrix(gmcfile);

  votca::tools::Table B;
  B.Load(imcfile);

  votca::tools::Table x;
  x.resize(B.size());
  x.x() = B.x();

  // Calculating https://en.wikipedia.org/wiki/Tikhonov_regularization

  Eigen::MatrixXd ATA = A.transpose() * A;

  // We could add and invert but for stability reasons we will diagonalize the
  // matrix which is symmetric by construction

  Eigen::SelfAdjointEigenSolver<Eigen::MatrixXd> es(ATA);

  Eigen::VectorXd inv_diag = Eigen::VectorXd::Zero(es.eigenvalues().size());
  double etol = 1e-12;

  int numerics_unstable = 0;
  // Constructing pseudoinverse if not stable
  // https://en.wikipedia.org/wiki/Moore%E2%80%93Penrose_inverse
  for (int i = 0; i < es.eigenvalues().size(); i++) {
    if (std::abs(es.eigenvalues()[i] + reg) < etol) {
      numerics_unstable++;
    } else {
      inv_diag[i] = 1 / (es.eigenvalues()[i] + reg);
    }
  }

  if (numerics_unstable > 0) {
    std::cout
        << "Regularisation parameter was to small, a pseudo inverse was "
           "constructed instead.\n Use a larger regularisation parameter R."
           " Smallest (eigenvalue+R)="
        << (es.eigenvalues().array() + reg).abs().minCoeff() << " Found "
        << numerics_unstable << " eigenvalues of " << es.eigenvalues().size()
        << " below " << etol << std::endl;
  }

  Eigen::MatrixXd inverse =
      es.eigenvectors() * inv_diag.asDiagonal() * es.eigenvectors().transpose();

  x.y() = inverse * A.transpose() * B.y();

  x.Save(outputfile);
}
<commit_msg>fixed bug in parser<commit_after>/*
 * Copyright 2009-2019 The VOTCA Development Team (http://www.votca.org)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

#include "csg_imc_solve.h"
#include <fstream>
#include <votca/tools/table.h>

int main(int argc, char** argv) {
  CG_IMC_solve app;
  return app.Exec(argc, argv);
}

void CG_IMC_solve::Initialize(void) {
  namespace propt = boost::program_options;

  AddProgramOptions()("regularization,r",
                      propt::value<double>()->default_value(0.0),
                      "regularization factor");

  AddProgramOptions()("imcfile,i", boost::program_options::value<std::string>(),
                      "imc statefile");

  AddProgramOptions()("gmcfile,g", boost::program_options::value<std::string>(),
                      "gmc statefile");

  AddProgramOptions()("outputfile,o",
                      boost::program_options::value<std::string>(),
                      "outputfile");
}

bool CG_IMC_solve::EvaluateOptions() {
  CheckRequired("imcfile", "Missing imcfile");
  CheckRequired("gmcfile", "Missing gmcfile");
  CheckRequired("outputfile", "Missing outputfile");
  return true;
}

Eigen::MatrixXd CG_IMC_solve::LoadMatrix(const std::string& filename) const {
  std::ifstream intt;
  intt.open(filename);
  if (!intt)
    throw std::runtime_error(std::string("error, cannot open file ") +
                             filename);

  std::string line;
  std::vector<double> result;
  int numrows = 0;
  unsigned numcols = 0;
  while (getline(intt, line)) {
    if (line[0] == '#') {
      continue;
    }
    votca::tools::Tokenizer tok(line, " \t");
    std::vector<std::string> tokens = tok.ToVector();
    if (numrows == 0) {
      numcols = tokens.size();
    } else if (numcols != tokens.size()) {
      throw std::runtime_error(
          "Matrix has not the same number of entries in each row.");
    }
    for (const std::string& s : tokens) {
      result.push_back(std::stod(s));
    }
    numrows++;
  }
  intt.close();

  return Eigen::Map<Eigen::MatrixXd>(result.data(), numrows, numcols);
}

void CG_IMC_solve::Run() {
  std::string imcfile = _op_vm["imcfile"].as<std::string>();
  std::string gmcfile = _op_vm["gmcfile"].as<std::string>();
  std::string outputfile = _op_vm["outputfile"].as<std::string>();

  double reg = _op_vm["regularization"].as<double>();

  Eigen::MatrixXd A = LoadMatrix(gmcfile);

  votca::tools::Table B;
  B.Load(imcfile);

  votca::tools::Table x;
  x.resize(B.size());
  x.x() = B.x();

  // Calculating https://en.wikipedia.org/wiki/Tikhonov_regularization

  Eigen::MatrixXd ATA = A.transpose() * A;

  // We could add and invert but for stability reasons we will diagonalize the
  // matrix which is symmetric by construction

  Eigen::SelfAdjointEigenSolver<Eigen::MatrixXd> es(ATA);

  Eigen::VectorXd inv_diag = Eigen::VectorXd::Zero(es.eigenvalues().size());
  double etol = 1e-12;

  int numerics_unstable = 0;
  // Constructing pseudoinverse if not stable
  // https://en.wikipedia.org/wiki/Moore%E2%80%93Penrose_inverse
  for (int i = 0; i < es.eigenvalues().size(); i++) {
    if (std::abs(es.eigenvalues()[i] + reg) < etol) {
      numerics_unstable++;
    } else {
      inv_diag[i] = 1 / (es.eigenvalues()[i] + reg);
    }
  }

  if (numerics_unstable > 0) {
    std::cout
        << "Regularisation parameter was to small, a pseudo inverse was "
           "constructed instead.\n Use a larger regularisation parameter R."
           " Smallest (eigenvalue+R)="
        << (es.eigenvalues().array() + reg).abs().minCoeff() << " Found "
        << numerics_unstable << " eigenvalues of " << es.eigenvalues().size()
        << " below " << etol << std::endl;
  }

  Eigen::MatrixXd inverse =
      es.eigenvectors() * inv_diag.asDiagonal() * es.eigenvectors().transpose();

  x.y() = inverse * A.transpose() * B.y();

  x.Save(outputfile);
}
<|endoftext|>


<commit_before>/* net6 - Library providing IPv4/IPv6 network access
 * Copyright (C) 2005, 2006 Armin Burgmeier / 0x539 dev group
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free
 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#include <fcntl.h>

#include "config.hpp"
#include "encrypt.hpp"

namespace
{
	const unsigned int DH_BITS = 1024;

	net6::gnutls_session_t create_session(gnutls_connection_end_t end)
	{
		net6::gnutls_session_t session;
		gnutls_init(&session, end);
		return session;
	}

#ifdef WIN32
	// Required to turn WSA error codes into errno.
	ssize_t net6_win32_send_func(net6::gnutls_transport_ptr_t ptr,
	                             const void* data,
	                             size_t size)
	{
		ssize_t ret = ::send(
			reinterpret_cast<SOCKET>(ptr),
			static_cast<const char*>(data),
			size,
			0
		);

		int error = WSAGetLastError();
		if(error == WSAEWOULDBLOCK) errno = EAGAIN;
		if(error == WSAEINTR) errno = EINTR;

		// Ensures that a second call to WSAGetLastError
		// has the same result
		WSASetLastError(error);
		return ret;
	}

	ssize_t net6_win32_recv_func(net6::gnutls_transport_ptr_t ptr,
	                             void* data,
	                             size_t size)
	{
		ssize_t ret = ::recv(
			reinterpret_cast<SOCKET>(ptr),
			static_cast<char*>(data),
			size,
			0
		);

		int error = WSAGetLastError();
		if(error == WSAEWOULDBLOCK) errno = EAGAIN;
		if(error == WSAEINTR) errno = EINTR;

		// Ensures that a second call to WSAGetLastError
		// has the same result
		WSASetLastError(error);
		return ret;
	}
#else
	// Send data with MSG_NOSIGNAL
	ssize_t net6_unix_send_func(net6::gnutls_transport_ptr_t ptr,
	                            const void* data,
	                            size_t size)
	{
		// TODO: How to properly get the fd from ptr?
		return send(
			static_cast<int>(reinterpret_cast<intptr_t>(ptr)),
			data,
			size,
#ifdef HAVE_MSG_NOSIGNAL
			// Linux
			MSG_NOSIGNAL
#else
			// Plain BSD
			0
#endif
		);
	}
#endif

	typedef net6::tcp_encrypted_socket_base::size_type
		io_size_type;
	typedef net6::tcp_encrypted_socket_base::handshake_state
		io_handshake_state;

	template<
		typename buffer_type,
		ssize_t(*func)(net6::gnutls_session_t, buffer_type, size_t)
	> io_size_type io_impl(const net6::gnutls_session_t session,
	                       buffer_type buf,
	                       io_size_type len,
	                       io_handshake_state state)
	{
		ssize_t ret;
		switch(state)
		{
		case net6::tcp_encrypted_socket_base::DEFAULT:
			throw std::logic_error(
				"net6::encrypt.cpp:io_impl:\n"
				"Handshake not yet performed"
			);

			break;
		case net6::tcp_encrypted_socket_base::HANDSHAKING:
			throw std::logic_error(
				"net6::encrypt.cpp:io_impl:\n"
				"IO tried while handshaking"
			);

			break;
		case net6::tcp_encrypted_socket_base::HANDSHAKED:
			ret = func(session, buf, len);
			if(ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED)
				func(session, NULL, 0);

			if(ret < 0)
				throw net6::error(net6::error::GNUTLS, ret);

			break;
		}

		return ret;
	}
}

net6::dh_params::dh_params():
	params(NULL)
{
	gnutls_dh_params_init(&params);
	gnutls_dh_params_generate2(params, DH_BITS);
}

net6::dh_params::dh_params(gnutls_dh_params_t initial_params):
	params(initial_params)
{
}

net6::dh_params::~dh_params()
{
	gnutls_dh_params_deinit(params);
}

net6::gnutls_dh_params_t net6::dh_params::cobj()
{
	return params;
}

const net6::gnutls_dh_params_t net6::dh_params::cobj() const
{
	return params;
}

net6::tcp_encrypted_socket_base::
	tcp_encrypted_socket_base(socket_type cobj,
                                  gnutls_session_t sess):
	tcp_client_socket(cobj), session(sess), state(DEFAULT)
{
	const int kx_prio[] = { GNUTLS_KX_ANON_DH, 0 };

	gnutls_set_default_priority(session);
	gnutls_kx_set_priority(session, kx_prio);

	gnutls_transport_set_ptr(
		session,
		reinterpret_cast<gnutls_transport_ptr_t>(cobj)
	);

#ifdef WIN32
	gnutls_transport_set_pull_function(
		session,
		net6_win32_recv_func
	);

	gnutls_transport_set_push_function(
		session,
		net6_win32_send_func
	);
#else
	gnutls_transport_set_push_function(
		session,
		net6_unix_send_func
	);
#endif

	gnutls_transport_set_lowat(session, 0);
}

net6::tcp_encrypted_socket_base::~tcp_encrypted_socket_base()
{
	gnutls_bye(session, GNUTLS_SHUT_WR);
	gnutls_deinit(session);
}

bool net6::tcp_encrypted_socket_base::handshake()
{
	if(state == HANDSHAKED)
	{
		throw std::logic_error(
			"net6::tcp_encrypted_socket_base::handshake:\n"
			"Handshake has already been performed"
		);
	}

	if(state == DEFAULT)
	{
#ifdef WIN32
		u_long iMode = 1;
		if(ioctlsocket(cobj(), FIONBIO, &iMode) == SOCKET_ERROR)
			throw net6::error(net6::error::SYSTEM);

		// TODO: How to find out whether the socket is in blocking
		// mode?
		was_blocking = false;
#else
		// Make socket nonblocking to allow to call handshake
		// multiple times
		int flags = fcntl(cobj(), F_GETFL);
		if(fcntl(cobj(), F_SETFL, flags | O_NONBLOCK) == -1)
			throw net6::error(net6::error::SYSTEM);

		was_blocking = ((flags & O_NONBLOCK) == 0);
#endif

		state = HANDSHAKING;
	}

	int ret = gnutls_handshake(session);

	if(ret == 0)
	{
		if(was_blocking)
		{
			// Remove nonblocking state for further handling,
			// so the socket behaves like a nonencrypted tcp
			// client socket.
#ifdef WIN32
		u_long iMode = 0;
		if(ioctlsocket(cobj(), FIONBIO, &iMode) == SOCKET_ERROR)
			throw net6::error(net6::error::SYSTEM);
#else
			int flags = fcntl(cobj(), F_GETFL);
			if(fcntl(cobj(), F_SETFL, flags & ~O_NONBLOCK) == -1)
				throw net6::error(net6::error::SYSTEM);
#endif
		}

		state = HANDSHAKED;
		return true;
	}

	if(ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED)
		return false;

	throw net6::error(net6::error::GNUTLS, ret);
}

bool net6::tcp_encrypted_socket_base::get_dir() const
{
	return gnutls_record_get_direction(session) == 1;
}

net6::tcp_encrypted_socket_base::size_type
net6::tcp_encrypted_socket_base::get_pending() const
{
	return gnutls_record_check_pending(session);
}

net6::tcp_encrypted_socket_base::size_type
net6::tcp_encrypted_socket_base::send(const void* buf, size_type len) const
{
	return ::io_impl<const void*, gnutls_record_send>(
		session, buf, len, state
	);
}

net6::tcp_encrypted_socket_base::size_type
net6::tcp_encrypted_socket_base::recv(void* buf, size_type len) const
{
	return ::io_impl<void*, gnutls_record_recv>(
		session, buf, len, state
	);
}

net6::tcp_encrypted_socket_client::
	tcp_encrypted_socket_client(tcp_client_socket& sock):
	tcp_encrypted_socket_base(sock.cobj(), create_session(GNUTLS_CLIENT) )
{
	sock.invalidate();

	gnutls_anon_allocate_client_credentials(&anoncred);
	gnutls_credentials_set(session, GNUTLS_CRD_ANON, anoncred);

	gnutls_dh_set_prime_bits(session, DH_BITS);
}

net6::tcp_encrypted_socket_client::~tcp_encrypted_socket_client()
{
	gnutls_anon_free_client_credentials(anoncred);
}

net6::tcp_encrypted_socket_server::
	tcp_encrypted_socket_server(tcp_client_socket& sock):
	tcp_encrypted_socket_base(sock.cobj(), create_session(GNUTLS_SERVER) ),
	own_params(new dh_params)
{
	sock.invalidate();

	gnutls_anon_allocate_server_credentials(&anoncred);
	gnutls_credentials_set(session, GNUTLS_CRD_ANON, anoncred);

	gnutls_anon_set_server_dh_params(anoncred, own_params->cobj());
}

net6::tcp_encrypted_socket_server::
	tcp_encrypted_socket_server(tcp_client_socket& sock,
	                            dh_params& params):
	tcp_encrypted_socket_base(sock.cobj(), create_session(GNUTLS_SERVER) )
{
	sock.invalidate();

	gnutls_anon_allocate_server_credentials(&anoncred);
	gnutls_credentials_set(session, GNUTLS_CRD_ANON, anoncred);

	gnutls_anon_set_server_dh_params(anoncred, params.cobj() );
}

net6::tcp_encrypted_socket_server::~tcp_encrypted_socket_server()
{
	gnutls_anon_free_server_credentials(anoncred);
}
<commit_msg>Fix build failure with gnutls 3.0.3 and above.<commit_after>/* net6 - Library providing IPv4/IPv6 network access
 * Copyright (C) 2005, 2006 Armin Burgmeier / 0x539 dev group
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free
 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#include <fcntl.h>

#include "config.hpp"
#include "encrypt.hpp"

namespace
{
	const unsigned int DH_BITS = 1024;

	net6::gnutls_session_t create_session(gnutls_connection_end_t end)
	{
		net6::gnutls_session_t session;
		gnutls_init(&session, end);
		return session;
	}

#ifdef WIN32
	// Required to turn WSA error codes into errno.
	ssize_t net6_win32_send_func(net6::gnutls_transport_ptr_t ptr,
	                             const void* data,
	                             size_t size)
	{
		ssize_t ret = ::send(
			reinterpret_cast<SOCKET>(ptr),
			static_cast<const char*>(data),
			size,
			0
		);

		int error = WSAGetLastError();
		if(error == WSAEWOULDBLOCK) errno = EAGAIN;
		if(error == WSAEINTR) errno = EINTR;

		// Ensures that a second call to WSAGetLastError
		// has the same result
		WSASetLastError(error);
		return ret;
	}

	ssize_t net6_win32_recv_func(net6::gnutls_transport_ptr_t ptr,
	                             void* data,
	                             size_t size)
	{
		ssize_t ret = ::recv(
			reinterpret_cast<SOCKET>(ptr),
			static_cast<char*>(data),
			size,
			0
		);

		int error = WSAGetLastError();
		if(error == WSAEWOULDBLOCK) errno = EAGAIN;
		if(error == WSAEINTR) errno = EINTR;

		// Ensures that a second call to WSAGetLastError
		// has the same result
		WSASetLastError(error);
		return ret;
	}
#else
	// Send data with MSG_NOSIGNAL
	ssize_t net6_unix_send_func(net6::gnutls_transport_ptr_t ptr,
	                            const void* data,
	                            size_t size)
	{
		// TODO: How to properly get the fd from ptr?
		return send(
			static_cast<int>(reinterpret_cast<intptr_t>(ptr)),
			data,
			size,
#ifdef HAVE_MSG_NOSIGNAL
			// Linux
			MSG_NOSIGNAL
#else
			// Plain BSD
			0
#endif
		);
	}
#endif

	typedef net6::tcp_encrypted_socket_base::size_type
		io_size_type;
	typedef net6::tcp_encrypted_socket_base::handshake_state
		io_handshake_state;

	template<
		typename buffer_type,
		ssize_t(*func)(net6::gnutls_session_t, buffer_type, size_t)
	> io_size_type io_impl(const net6::gnutls_session_t session,
	                       buffer_type buf,
	                       io_size_type len,
	                       io_handshake_state state)
	{
		ssize_t ret;
		switch(state)
		{
		case net6::tcp_encrypted_socket_base::DEFAULT:
			throw std::logic_error(
				"net6::encrypt.cpp:io_impl:\n"
				"Handshake not yet performed"
			);

			break;
		case net6::tcp_encrypted_socket_base::HANDSHAKING:
			throw std::logic_error(
				"net6::encrypt.cpp:io_impl:\n"
				"IO tried while handshaking"
			);

			break;
		case net6::tcp_encrypted_socket_base::HANDSHAKED:
			ret = func(session, buf, len);
			if(ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED)
				func(session, NULL, 0);

			if(ret < 0)
				throw net6::error(net6::error::GNUTLS, ret);

			break;
		}

		return ret;
	}
}

net6::dh_params::dh_params():
	params(NULL)
{
	gnutls_dh_params_init(&params);
	gnutls_dh_params_generate2(params, DH_BITS);
}

net6::dh_params::dh_params(gnutls_dh_params_t initial_params):
	params(initial_params)
{
}

net6::dh_params::~dh_params()
{
	gnutls_dh_params_deinit(params);
}

net6::gnutls_dh_params_t net6::dh_params::cobj()
{
	return params;
}

const net6::gnutls_dh_params_t net6::dh_params::cobj() const
{
	return params;
}

net6::tcp_encrypted_socket_base::
	tcp_encrypted_socket_base(socket_type cobj,
                                  gnutls_session_t sess):
	tcp_client_socket(cobj), session(sess), state(DEFAULT)
{
	const int kx_prio[] = { GNUTLS_KX_ANON_DH, 0 };

	gnutls_set_default_priority(session);
	gnutls_kx_set_priority(session, kx_prio);

	gnutls_transport_set_ptr(
		session,
		reinterpret_cast<gnutls_transport_ptr_t>(cobj)
	);

#ifdef WIN32
	gnutls_transport_set_pull_function(
		session,
		net6_win32_recv_func
	);

	gnutls_transport_set_push_function(
		session,
		net6_win32_send_func
	);
#else
	gnutls_transport_set_push_function(
		session,
		net6_unix_send_func
	);
#endif

#if GNUTLS_VERSION_NUMBER < 0x030003
	gnutls_transport_set_lowat(session, 0);
#endif
}

net6::tcp_encrypted_socket_base::~tcp_encrypted_socket_base()
{
	gnutls_bye(session, GNUTLS_SHUT_WR);
	gnutls_deinit(session);
}

bool net6::tcp_encrypted_socket_base::handshake()
{
	if(state == HANDSHAKED)
	{
		throw std::logic_error(
			"net6::tcp_encrypted_socket_base::handshake:\n"
			"Handshake has already been performed"
		);
	}

	if(state == DEFAULT)
	{
#ifdef WIN32
		u_long iMode = 1;
		if(ioctlsocket(cobj(), FIONBIO, &iMode) == SOCKET_ERROR)
			throw net6::error(net6::error::SYSTEM);

		// TODO: How to find out whether the socket is in blocking
		// mode?
		was_blocking = false;
#else
		// Make socket nonblocking to allow to call handshake
		// multiple times
		int flags = fcntl(cobj(), F_GETFL);
		if(fcntl(cobj(), F_SETFL, flags | O_NONBLOCK) == -1)
			throw net6::error(net6::error::SYSTEM);

		was_blocking = ((flags & O_NONBLOCK) == 0);
#endif

		state = HANDSHAKING;
	}

	int ret = gnutls_handshake(session);

	if(ret == 0)
	{
		if(was_blocking)
		{
			// Remove nonblocking state for further handling,
			// so the socket behaves like a nonencrypted tcp
			// client socket.
#ifdef WIN32
		u_long iMode = 0;
		if(ioctlsocket(cobj(), FIONBIO, &iMode) == SOCKET_ERROR)
			throw net6::error(net6::error::SYSTEM);
#else
			int flags = fcntl(cobj(), F_GETFL);
			if(fcntl(cobj(), F_SETFL, flags & ~O_NONBLOCK) == -1)
				throw net6::error(net6::error::SYSTEM);
#endif
		}

		state = HANDSHAKED;
		return true;
	}

	if(ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED)
		return false;

	throw net6::error(net6::error::GNUTLS, ret);
}

bool net6::tcp_encrypted_socket_base::get_dir() const
{
	return gnutls_record_get_direction(session) == 1;
}

net6::tcp_encrypted_socket_base::size_type
net6::tcp_encrypted_socket_base::get_pending() const
{
	return gnutls_record_check_pending(session);
}

net6::tcp_encrypted_socket_base::size_type
net6::tcp_encrypted_socket_base::send(const void* buf, size_type len) const
{
	return ::io_impl<const void*, gnutls_record_send>(
		session, buf, len, state
	);
}

net6::tcp_encrypted_socket_base::size_type
net6::tcp_encrypted_socket_base::recv(void* buf, size_type len) const
{
	return ::io_impl<void*, gnutls_record_recv>(
		session, buf, len, state
	);
}

net6::tcp_encrypted_socket_client::
	tcp_encrypted_socket_client(tcp_client_socket& sock):
	tcp_encrypted_socket_base(sock.cobj(), create_session(GNUTLS_CLIENT) )
{
	sock.invalidate();

	gnutls_anon_allocate_client_credentials(&anoncred);
	gnutls_credentials_set(session, GNUTLS_CRD_ANON, anoncred);

	gnutls_dh_set_prime_bits(session, DH_BITS);
}

net6::tcp_encrypted_socket_client::~tcp_encrypted_socket_client()
{
	gnutls_anon_free_client_credentials(anoncred);
}

net6::tcp_encrypted_socket_server::
	tcp_encrypted_socket_server(tcp_client_socket& sock):
	tcp_encrypted_socket_base(sock.cobj(), create_session(GNUTLS_SERVER) ),
	own_params(new dh_params)
{
	sock.invalidate();

	gnutls_anon_allocate_server_credentials(&anoncred);
	gnutls_credentials_set(session, GNUTLS_CRD_ANON, anoncred);

	gnutls_anon_set_server_dh_params(anoncred, own_params->cobj());
}

net6::tcp_encrypted_socket_server::
	tcp_encrypted_socket_server(tcp_client_socket& sock,
	                            dh_params& params):
	tcp_encrypted_socket_base(sock.cobj(), create_session(GNUTLS_SERVER) )
{
	sock.invalidate();

	gnutls_anon_allocate_server_credentials(&anoncred);
	gnutls_credentials_set(session, GNUTLS_CRD_ANON, anoncred);

	gnutls_anon_set_server_dh_params(anoncred, params.cobj() );
}

net6::tcp_encrypted_socket_server::~tcp_encrypted_socket_server()
{
	gnutls_anon_free_server_credentials(anoncred);
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2013-2014, Georgia Tech Research Corporation
 * All rights reserved.
 *
 * Author(s): Jeongseok Lee <jslee02@gmail.com>
 *
 * Georgia Tech Graphics Lab and Humanoid Robotics Lab
 *
 * Directed by Prof. C. Karen Liu and Prof. Mike Stilman
 * <karenliu@cc.gatech.edu> <mstilman@cc.gatech.edu>
 *
 * This file is provided under the following "BSD-style" License:
 *   Redistribution and use in source and binary forms, with or
 *   without modification, are permitted provided that the following
 *   conditions are met:
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above
 *     copyright notice, this list of conditions and the following
 *     disclaimer in the documentation and/or other materials provided
 *     with the distribution.
 *   * This code incorporates portions of Open Dynamics Engine
 *     (Copyright (c) 2001-2004, Russell L. Smith. All rights
 *     reserved.) and portions of FCL (Copyright (c) 2011, Willow
 *     Garage, Inc. All rights reserved.), which were released under
 *     the same BSD license as below
 *
 *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
 *   CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
 *   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 *   MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 *   DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
 *   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 *   USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 *   AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 *   LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 *   ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *   POSSIBILITY OF SUCH DAMAGE.
 */

#include <iostream>

#include "dart/utils/Paths.h"
#include "dart/utils/SoftParser.h"
#include "dart/simulation/SoftWorld.h"
#include "apps/softCubes/MyWindow.h"

int main(int argc, char* argv[])
{
  // load a skeleton file
  // create and initialize the world
  dart::simulation::SoftWorld* myWorld
      = dart::utils::SoftSkelParser::readSoftFile(
          DART_DATA_PATH"skel/soft_fullbody1.skel");
  assert(myWorld != NULL);

  // create a window and link it to the world
  MyWindow window;
  window.setWorld(myWorld);

  std::cout << "space bar: simulation on/off" << std::endl;
  std::cout << "'p': playback/stop" << std::endl;
  std::cout << "'[' and ']': play one frame backward and forward" << std::endl;
  std::cout << "'v': visualization on/off" << std::endl;
  std::cout << "'1'--'4': programmed interaction" << std::endl;

  glutInit(&argc, argv);
  window.initWindow(640, 480, "Soft Cubes");
  glutMainLoop();

  return 0;
}
<commit_msg>Revert unintended change on soft Cubes app<commit_after>/*
 * Copyright (c) 2013-2014, Georgia Tech Research Corporation
 * All rights reserved.
 *
 * Author(s): Jeongseok Lee <jslee02@gmail.com>
 *
 * Georgia Tech Graphics Lab and Humanoid Robotics Lab
 *
 * Directed by Prof. C. Karen Liu and Prof. Mike Stilman
 * <karenliu@cc.gatech.edu> <mstilman@cc.gatech.edu>
 *
 * This file is provided under the following "BSD-style" License:
 *   Redistribution and use in source and binary forms, with or
 *   without modification, are permitted provided that the following
 *   conditions are met:
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above
 *     copyright notice, this list of conditions and the following
 *     disclaimer in the documentation and/or other materials provided
 *     with the distribution.
 *   * This code incorporates portions of Open Dynamics Engine
 *     (Copyright (c) 2001-2004, Russell L. Smith. All rights
 *     reserved.) and portions of FCL (Copyright (c) 2011, Willow
 *     Garage, Inc. All rights reserved.), which were released under
 *     the same BSD license as below
 *
 *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
 *   CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
 *   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 *   MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 *   DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
 *   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 *   USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 *   AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 *   LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 *   ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *   POSSIBILITY OF SUCH DAMAGE.
 */

#include <iostream>

#include "dart/utils/Paths.h"
#include "dart/utils/SoftParser.h"
#include "dart/simulation/SoftWorld.h"
#include "apps/softCubes/MyWindow.h"

int main(int argc, char* argv[])
{
  // load a skeleton file
  // create and initialize the world
  dart::simulation::SoftWorld* myWorld
      = dart::utils::SoftSkelParser::readSoftFile(
          DART_DATA_PATH"skel/soft_cubes.skel");
  assert(myWorld != NULL);

  // create a window and link it to the world
  MyWindow window;
  window.setWorld(myWorld);

  std::cout << "space bar: simulation on/off" << std::endl;
  std::cout << "'p': playback/stop" << std::endl;
  std::cout << "'[' and ']': play one frame backward and forward" << std::endl;
  std::cout << "'v': visualization on/off" << std::endl;
  std::cout << "'1'--'4': programmed interaction" << std::endl;

  glutInit(&argc, argv);
  window.initWindow(640, 480, "Soft Cubes");
  glutMainLoop();

  return 0;
}
<|endoftext|>


<commit_before>//===- CodeEmitterGen.cpp - Code Emitter Generator ------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// CodeEmitterGen uses the descriptions of instructions and their fields to
// construct an automated code emitter: a function that, given a MachineInstr,
// returns the (currently, 32-bit unsigned) value of the instruction.
//
//===----------------------------------------------------------------------===//

#include "CodeEmitterGen.h"
#include "CodeGenTarget.h"
#include "Record.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/Debug.h"
using namespace llvm;

void CodeEmitterGen::reverseBits(std::vector<Record*> &Insts) {
  for (std::vector<Record*>::iterator I = Insts.begin(), E = Insts.end();
       I != E; ++I) {
    Record *R = *I;
    if (R->getName() == "PHI" ||
        R->getName() == "INLINEASM" ||
        R->getName() == "DBG_LABEL" ||
        R->getName() == "EH_LABEL" ||
        R->getName() == "GC_LABEL" ||
        R->getName() == "KILL" ||
        R->getName() == "EXTRACT_SUBREG" ||
        R->getName() == "INSERT_SUBREG" ||
        R->getName() == "IMPLICIT_DEF" ||
        R->getName() == "SUBREG_TO_REG" ||
        R->getName() == "COPY_TO_REGCLASS" ||
        R->getName() == "DBG_VALUE") continue;

    BitsInit *BI = R->getValueAsBitsInit("Inst");

    unsigned numBits = BI->getNumBits();
    BitsInit *NewBI = new BitsInit(numBits);
    for (unsigned bit = 0, end = numBits / 2; bit != end; ++bit) {
      unsigned bitSwapIdx = numBits - bit - 1;
      Init *OrigBit = BI->getBit(bit);
      Init *BitSwap = BI->getBit(bitSwapIdx);
      NewBI->setBit(bit, BitSwap);
      NewBI->setBit(bitSwapIdx, OrigBit);
    }
    if (numBits % 2) {
      unsigned middle = (numBits + 1) / 2;
      NewBI->setBit(middle, BI->getBit(middle));
    }

    // Update the bits in reversed order so that emitInstrOpBits will get the
    // correct endianness.
    R->getValue("Inst")->setValue(NewBI);
  }
}

// If the VarBitInit at position 'bit' matches the specified variable then
// return the variable bit position.  Otherwise return -1.
int CodeEmitterGen::getVariableBit(const std::string &VarName,
            BitsInit *BI, int bit) {
  if (VarBitInit *VBI = dynamic_cast<VarBitInit*>(BI->getBit(bit))) {
    TypedInit *TI = VBI->getVariable();

    if (VarInit *VI = dynamic_cast<VarInit*>(TI)) {
      if (VI->getName() == VarName) return VBI->getBitNum();
    }
  }

  return -1;
}

void CodeEmitterGen::run(raw_ostream &o) {
  CodeGenTarget Target;
  std::vector<Record*> Insts = Records.getAllDerivedDefinitions("Instruction");

  // For little-endian instruction bit encodings, reverse the bit order
  if (Target.isLittleEndianEncoding()) reverseBits(Insts);

  EmitSourceFileHeader("Machine Code Emitter", o);
  std::string Namespace = Insts[0]->getValueAsString("Namespace") + "::";

  const std::vector<const CodeGenInstruction*> &NumberedInstructions =
    Target.getInstructionsByEnumValue();

  // Emit function declaration
  o << "unsigned " << Target.getName() << "CodeEmitter::"
    << "getBinaryCodeForInstr(const MachineInstr &MI) {\n";

  // Emit instruction base values
  o << "  static const unsigned InstBits[] = {\n";
  for (std::vector<const CodeGenInstruction*>::const_iterator
          IN = NumberedInstructions.begin(),
          EN = NumberedInstructions.end();
       IN != EN; ++IN) {
    const CodeGenInstruction *CGI = *IN;
    Record *R = CGI->TheDef;

    if (R->getName() == "PHI" ||
        R->getName() == "INLINEASM" ||
        R->getName() == "DBG_LABEL" ||
        R->getName() == "EH_LABEL" ||
        R->getName() == "GC_LABEL" ||
        R->getName() == "KILL" ||
        R->getName() == "EXTRACT_SUBREG" ||
        R->getName() == "INSERT_SUBREG" ||
        R->getName() == "IMPLICIT_DEF" ||
        R->getName() == "SUBREG_TO_REG" ||
        R->getName() == "COPY_TO_REGCLASS" ||
        R->getName() == "DBG_VALUE") {
      o << "    0U,\n";
      continue;
    }

    BitsInit *BI = R->getValueAsBitsInit("Inst");

    // Start by filling in fixed values...
    unsigned Value = 0;
    for (unsigned i = 0, e = BI->getNumBits(); i != e; ++i) {
      if (BitInit *B = dynamic_cast<BitInit*>(BI->getBit(e-i-1))) {
        Value |= B->getValue() << (e-i-1);
      }
    }
    o << "    " << Value << "U," << '\t' << "// " << R->getName() << "\n";
  }
  o << "    0U\n  };\n";

  // Map to accumulate all the cases.
  std::map<std::string, std::vector<std::string> > CaseMap;

  // Construct all cases statement for each opcode
  for (std::vector<Record*>::iterator IC = Insts.begin(), EC = Insts.end();
        IC != EC; ++IC) {
    Record *R = *IC;
    const std::string &InstName = R->getName();
    std::string Case("");

    if (InstName == "PHI" ||
        InstName == "INLINEASM" ||
        InstName == "DBG_LABEL"||
        InstName == "EH_LABEL"||
        InstName == "GC_LABEL"||
        InstName == "KILL"||
        InstName == "EXTRACT_SUBREG" ||
        InstName == "INSERT_SUBREG" ||
        InstName == "IMPLICIT_DEF" ||
        InstName == "SUBREG_TO_REG" ||
        InstName == "COPY_TO_REGCLASS" ||
        InstName == "DBG_VALUE") continue;

    BitsInit *BI = R->getValueAsBitsInit("Inst");
    const std::vector<RecordVal> &Vals = R->getValues();
    CodeGenInstruction &CGI = Target.getInstruction(R);

    // Loop over all of the fields in the instruction, determining which are the
    // operands to the instruction.
    unsigned op = 0;
    for (unsigned i = 0, e = Vals.size(); i != e; ++i) {
      if (!Vals[i].getPrefix() && !Vals[i].getValue()->isComplete()) {
        // Is the operand continuous? If so, we can just mask and OR it in
        // instead of doing it bit-by-bit, saving a lot in runtime cost.
        const std::string &VarName = Vals[i].getName();
        bool gotOp = false;

        for (int bit = BI->getNumBits()-1; bit >= 0; ) {
          int varBit = getVariableBit(VarName, BI, bit);

          if (varBit == -1) {
            --bit;
          } else {
            int beginInstBit = bit;
            int beginVarBit = varBit;
            int N = 1;

            for (--bit; bit >= 0;) {
              varBit = getVariableBit(VarName, BI, bit);
              if (varBit == -1 || varBit != (beginVarBit - N)) break;
              ++N;
              --bit;
            }

            if (!gotOp) {
              /// If this operand is not supposed to be emitted by the generated
              /// emitter, skip it.
              while (CGI.isFlatOperandNotEmitted(op))
                ++op;

              Case += "      // op: " + VarName + "\n"
                   +  "      op = getMachineOpValue(MI, MI.getOperand("
                   +  utostr(op++) + "));\n";
              gotOp = true;
            }

            unsigned opMask = ~0U >> (32-N);
            int opShift = beginVarBit - N + 1;
            opMask <<= opShift;
            opShift = beginInstBit - beginVarBit;

            if (opShift > 0) {
              Case += "      Value |= (op & " + utostr(opMask) + "U) << "
                   +  itostr(opShift) + ";\n";
            } else if (opShift < 0) {
              Case += "      Value |= (op & " + utostr(opMask) + "U) >> "
                   +  itostr(-opShift) + ";\n";
            } else {
              Case += "      Value |= op & " + utostr(opMask) + "U;\n";
            }
          }
        }
      }
    }

    std::vector<std::string> &InstList = CaseMap[Case];
    InstList.push_back(InstName);
  }

  // Emit initial function code
  o << "  const unsigned opcode = MI.getOpcode();\n"
    << "  unsigned Value = InstBits[opcode];\n"
    << "  unsigned op = 0;\n"
    << "  op = op;  // suppress warning\n"
    << "  switch (opcode) {\n";

  // Emit each case statement
  std::map<std::string, std::vector<std::string> >::iterator IE, EE;
  for (IE = CaseMap.begin(), EE = CaseMap.end(); IE != EE; ++IE) {
    const std::string &Case = IE->first;
    std::vector<std::string> &InstList = IE->second;

    for (int i = 0, N = InstList.size(); i < N; i++) {
      if (i) o << "\n";
      o << "    case " << Namespace << InstList[i]  << ":";
    }
    o << " {\n";
    o << Case;
    o << "      break;\n"
      << "    }\n";
  }

  // Default case: unhandled opcode
  o << "  default:\n"
    << "    std::string msg;\n"
    << "    raw_string_ostream Msg(msg);\n"
    << "    Msg << \"Not supported instr: \" << MI;\n"
    << "    llvm_report_error(Msg.str());\n"
    << "  }\n"
    << "  return Value;\n"
    << "}\n\n";
}
<commit_msg>rename llvm::llvm_report_error -> llvm::report_fatal_error<commit_after>//===- CodeEmitterGen.cpp - Code Emitter Generator ------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// CodeEmitterGen uses the descriptions of instructions and their fields to
// construct an automated code emitter: a function that, given a MachineInstr,
// returns the (currently, 32-bit unsigned) value of the instruction.
//
//===----------------------------------------------------------------------===//

#include "CodeEmitterGen.h"
#include "CodeGenTarget.h"
#include "Record.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/Debug.h"
using namespace llvm;

void CodeEmitterGen::reverseBits(std::vector<Record*> &Insts) {
  for (std::vector<Record*>::iterator I = Insts.begin(), E = Insts.end();
       I != E; ++I) {
    Record *R = *I;
    if (R->getName() == "PHI" ||
        R->getName() == "INLINEASM" ||
        R->getName() == "DBG_LABEL" ||
        R->getName() == "EH_LABEL" ||
        R->getName() == "GC_LABEL" ||
        R->getName() == "KILL" ||
        R->getName() == "EXTRACT_SUBREG" ||
        R->getName() == "INSERT_SUBREG" ||
        R->getName() == "IMPLICIT_DEF" ||
        R->getName() == "SUBREG_TO_REG" ||
        R->getName() == "COPY_TO_REGCLASS" ||
        R->getName() == "DBG_VALUE") continue;

    BitsInit *BI = R->getValueAsBitsInit("Inst");

    unsigned numBits = BI->getNumBits();
    BitsInit *NewBI = new BitsInit(numBits);
    for (unsigned bit = 0, end = numBits / 2; bit != end; ++bit) {
      unsigned bitSwapIdx = numBits - bit - 1;
      Init *OrigBit = BI->getBit(bit);
      Init *BitSwap = BI->getBit(bitSwapIdx);
      NewBI->setBit(bit, BitSwap);
      NewBI->setBit(bitSwapIdx, OrigBit);
    }
    if (numBits % 2) {
      unsigned middle = (numBits + 1) / 2;
      NewBI->setBit(middle, BI->getBit(middle));
    }

    // Update the bits in reversed order so that emitInstrOpBits will get the
    // correct endianness.
    R->getValue("Inst")->setValue(NewBI);
  }
}

// If the VarBitInit at position 'bit' matches the specified variable then
// return the variable bit position.  Otherwise return -1.
int CodeEmitterGen::getVariableBit(const std::string &VarName,
            BitsInit *BI, int bit) {
  if (VarBitInit *VBI = dynamic_cast<VarBitInit*>(BI->getBit(bit))) {
    TypedInit *TI = VBI->getVariable();

    if (VarInit *VI = dynamic_cast<VarInit*>(TI)) {
      if (VI->getName() == VarName) return VBI->getBitNum();
    }
  }

  return -1;
}

void CodeEmitterGen::run(raw_ostream &o) {
  CodeGenTarget Target;
  std::vector<Record*> Insts = Records.getAllDerivedDefinitions("Instruction");

  // For little-endian instruction bit encodings, reverse the bit order
  if (Target.isLittleEndianEncoding()) reverseBits(Insts);

  EmitSourceFileHeader("Machine Code Emitter", o);
  std::string Namespace = Insts[0]->getValueAsString("Namespace") + "::";

  const std::vector<const CodeGenInstruction*> &NumberedInstructions =
    Target.getInstructionsByEnumValue();

  // Emit function declaration
  o << "unsigned " << Target.getName() << "CodeEmitter::"
    << "getBinaryCodeForInstr(const MachineInstr &MI) {\n";

  // Emit instruction base values
  o << "  static const unsigned InstBits[] = {\n";
  for (std::vector<const CodeGenInstruction*>::const_iterator
          IN = NumberedInstructions.begin(),
          EN = NumberedInstructions.end();
       IN != EN; ++IN) {
    const CodeGenInstruction *CGI = *IN;
    Record *R = CGI->TheDef;

    if (R->getName() == "PHI" ||
        R->getName() == "INLINEASM" ||
        R->getName() == "DBG_LABEL" ||
        R->getName() == "EH_LABEL" ||
        R->getName() == "GC_LABEL" ||
        R->getName() == "KILL" ||
        R->getName() == "EXTRACT_SUBREG" ||
        R->getName() == "INSERT_SUBREG" ||
        R->getName() == "IMPLICIT_DEF" ||
        R->getName() == "SUBREG_TO_REG" ||
        R->getName() == "COPY_TO_REGCLASS" ||
        R->getName() == "DBG_VALUE") {
      o << "    0U,\n";
      continue;
    }

    BitsInit *BI = R->getValueAsBitsInit("Inst");

    // Start by filling in fixed values...
    unsigned Value = 0;
    for (unsigned i = 0, e = BI->getNumBits(); i != e; ++i) {
      if (BitInit *B = dynamic_cast<BitInit*>(BI->getBit(e-i-1))) {
        Value |= B->getValue() << (e-i-1);
      }
    }
    o << "    " << Value << "U," << '\t' << "// " << R->getName() << "\n";
  }
  o << "    0U\n  };\n";

  // Map to accumulate all the cases.
  std::map<std::string, std::vector<std::string> > CaseMap;

  // Construct all cases statement for each opcode
  for (std::vector<Record*>::iterator IC = Insts.begin(), EC = Insts.end();
        IC != EC; ++IC) {
    Record *R = *IC;
    const std::string &InstName = R->getName();
    std::string Case("");

    if (InstName == "PHI" ||
        InstName == "INLINEASM" ||
        InstName == "DBG_LABEL"||
        InstName == "EH_LABEL"||
        InstName == "GC_LABEL"||
        InstName == "KILL"||
        InstName == "EXTRACT_SUBREG" ||
        InstName == "INSERT_SUBREG" ||
        InstName == "IMPLICIT_DEF" ||
        InstName == "SUBREG_TO_REG" ||
        InstName == "COPY_TO_REGCLASS" ||
        InstName == "DBG_VALUE") continue;

    BitsInit *BI = R->getValueAsBitsInit("Inst");
    const std::vector<RecordVal> &Vals = R->getValues();
    CodeGenInstruction &CGI = Target.getInstruction(R);

    // Loop over all of the fields in the instruction, determining which are the
    // operands to the instruction.
    unsigned op = 0;
    for (unsigned i = 0, e = Vals.size(); i != e; ++i) {
      if (!Vals[i].getPrefix() && !Vals[i].getValue()->isComplete()) {
        // Is the operand continuous? If so, we can just mask and OR it in
        // instead of doing it bit-by-bit, saving a lot in runtime cost.
        const std::string &VarName = Vals[i].getName();
        bool gotOp = false;

        for (int bit = BI->getNumBits()-1; bit >= 0; ) {
          int varBit = getVariableBit(VarName, BI, bit);

          if (varBit == -1) {
            --bit;
          } else {
            int beginInstBit = bit;
            int beginVarBit = varBit;
            int N = 1;

            for (--bit; bit >= 0;) {
              varBit = getVariableBit(VarName, BI, bit);
              if (varBit == -1 || varBit != (beginVarBit - N)) break;
              ++N;
              --bit;
            }

            if (!gotOp) {
              /// If this operand is not supposed to be emitted by the generated
              /// emitter, skip it.
              while (CGI.isFlatOperandNotEmitted(op))
                ++op;

              Case += "      // op: " + VarName + "\n"
                   +  "      op = getMachineOpValue(MI, MI.getOperand("
                   +  utostr(op++) + "));\n";
              gotOp = true;
            }

            unsigned opMask = ~0U >> (32-N);
            int opShift = beginVarBit - N + 1;
            opMask <<= opShift;
            opShift = beginInstBit - beginVarBit;

            if (opShift > 0) {
              Case += "      Value |= (op & " + utostr(opMask) + "U) << "
                   +  itostr(opShift) + ";\n";
            } else if (opShift < 0) {
              Case += "      Value |= (op & " + utostr(opMask) + "U) >> "
                   +  itostr(-opShift) + ";\n";
            } else {
              Case += "      Value |= op & " + utostr(opMask) + "U;\n";
            }
          }
        }
      }
    }

    std::vector<std::string> &InstList = CaseMap[Case];
    InstList.push_back(InstName);
  }

  // Emit initial function code
  o << "  const unsigned opcode = MI.getOpcode();\n"
    << "  unsigned Value = InstBits[opcode];\n"
    << "  unsigned op = 0;\n"
    << "  op = op;  // suppress warning\n"
    << "  switch (opcode) {\n";

  // Emit each case statement
  std::map<std::string, std::vector<std::string> >::iterator IE, EE;
  for (IE = CaseMap.begin(), EE = CaseMap.end(); IE != EE; ++IE) {
    const std::string &Case = IE->first;
    std::vector<std::string> &InstList = IE->second;

    for (int i = 0, N = InstList.size(); i < N; i++) {
      if (i) o << "\n";
      o << "    case " << Namespace << InstList[i]  << ":";
    }
    o << " {\n";
    o << Case;
    o << "      break;\n"
      << "    }\n";
  }

  // Default case: unhandled opcode
  o << "  default:\n"
    << "    std::string msg;\n"
    << "    raw_string_ostream Msg(msg);\n"
    << "    Msg << \"Not supported instr: \" << MI;\n"
    << "    report_fatal_error(Msg.str());\n"
    << "  }\n"
    << "  return Value;\n"
    << "}\n\n";
}
<|endoftext|>


<commit_before>// Copyright (c) 2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/compiler_specific.h"
#include "base/lock.h"
#include "base/platform_thread.h"
#include "base/simple_thread.h"
#include "base/thread_collision_warner.h"
#include "testing/gtest/include/gtest/gtest.h"

// '' : local class member function does not have a body
MSVC_PUSH_DISABLE_WARNING(4822)

namespace {

// This is the asserter used with ThreadCollisionWarner instead of the default
// DCheckAsserter. The method fail_state is used to know if a collision took
// place.
class AssertReporter : public base::AsserterBase {
 public:
  AssertReporter()
      : failed_(false) {}

  virtual void warn() {
    failed_ = true;
  }

  virtual ~AssertReporter() {}

  bool fail_state() const { return failed_; }
  void reset() { failed_ = false; }

 private:
  bool failed_;
};

}  // namespace

TEST(ThreadCollisionTest, BookCriticalSection) {
  AssertReporter* local_reporter = new AssertReporter();

  base::ThreadCollisionWarner warner(local_reporter);
  EXPECT_FALSE(local_reporter->fail_state());

  {  // Pin section.
    DFAKE_SCOPED_LOCK_THREAD_LOCKED(warner);
    EXPECT_FALSE(local_reporter->fail_state());
    {  // Pin section.
      DFAKE_SCOPED_LOCK_THREAD_LOCKED(warner);
      EXPECT_FALSE(local_reporter->fail_state());
    }
  }
}

TEST(ThreadCollisionTest, ScopedRecursiveBookCriticalSection) {
  AssertReporter* local_reporter = new AssertReporter();

  base::ThreadCollisionWarner warner(local_reporter);
  EXPECT_FALSE(local_reporter->fail_state());

  {  // Pin section.
    DFAKE_SCOPED_RECURSIVE_LOCK(warner);
    EXPECT_FALSE(local_reporter->fail_state());
    {  // Pin section again (allowed by DFAKE_SCOPED_RECURSIVE_LOCK)
      DFAKE_SCOPED_RECURSIVE_LOCK(warner);
      EXPECT_FALSE(local_reporter->fail_state());
    }  // Unpin section.
  }  // Unpin section.

  // Check that section is not pinned
  {  // Pin section.
    DFAKE_SCOPED_LOCK(warner);
    EXPECT_FALSE(local_reporter->fail_state());
  }  // Unpin section.
}

TEST(ThreadCollisionTest, ScopedBookCriticalSection) {
  AssertReporter* local_reporter = new AssertReporter();

  base::ThreadCollisionWarner warner(local_reporter);
  EXPECT_FALSE(local_reporter->fail_state());

  {  // Pin section.
    DFAKE_SCOPED_LOCK(warner);
    EXPECT_FALSE(local_reporter->fail_state());
  }  // Unpin section.

  {  // Pin section.
    DFAKE_SCOPED_LOCK(warner);
    EXPECT_FALSE(local_reporter->fail_state());
    {
      // Pin section again (not allowed by DFAKE_SCOPED_LOCK)
      DFAKE_SCOPED_LOCK(warner);
#if !defined(NDEBUG)
      EXPECT_TRUE(local_reporter->fail_state());
#else
      EXPECT_FALSE(local_reporter->fail_state());
#endif
      // Reset the status of warner for further tests.
      local_reporter->reset();
    }  // Unpin section.
  }  // Unpin section.

  {
    // Pin section.
    DFAKE_SCOPED_LOCK(warner);
    EXPECT_FALSE(local_reporter->fail_state());
  }  // Unpin section.
}

TEST(ThreadCollisionTest, MTBookCriticalSectionTest) {
  class NonThreadSafeQueue {
   public:
    explicit NonThreadSafeQueue(base::AsserterBase* asserter)
#if !defined(NDEBUG)
        : push_pop_(asserter)
#endif
    { }

    void push(int value) {
      DFAKE_SCOPED_LOCK_THREAD_LOCKED(push_pop_);
    }

    int pop() {
      DFAKE_SCOPED_LOCK_THREAD_LOCKED(push_pop_);
      return 0;
    }

   private:
    DFAKE_MUTEX(push_pop_);

    DISALLOW_COPY_AND_ASSIGN(NonThreadSafeQueue);
  };

  class QueueUser : public base::DelegateSimpleThread::Delegate {
   public:
    explicit QueueUser(NonThreadSafeQueue& queue)
        : queue_(queue) {}

    virtual void Run() {
      queue_.push(0);
      queue_.pop();
    }

   private:
    NonThreadSafeQueue& queue_;
  };

  AssertReporter* local_reporter = new AssertReporter();

  NonThreadSafeQueue queue(local_reporter);

  QueueUser queue_user_a(queue);
  QueueUser queue_user_b(queue);

  base::DelegateSimpleThread thread_a(&queue_user_a, "queue_user_thread_a");
  base::DelegateSimpleThread thread_b(&queue_user_b, "queue_user_thread_b");

  thread_a.Start();
  thread_b.Start();

  thread_a.Join();
  thread_b.Join();

#if !defined(NDEBUG)
  EXPECT_TRUE(local_reporter->fail_state());
#else
  EXPECT_FALSE(local_reporter->fail_state());
#endif
}

TEST(ThreadCollisionTest, MTScopedBookCriticalSectionTest) {
  // Queue with a 5 seconds push execution time, hopefuly the two used threads
  // in the test will enter the push at same time.
  class NonThreadSafeQueue {
   public:
    explicit NonThreadSafeQueue(base::AsserterBase* asserter)
#if !defined(NDEBUG)
        : push_pop_(asserter)
#endif
    { }

    void push(int value) {
      DFAKE_SCOPED_LOCK(push_pop_);
      PlatformThread::Sleep(5000);
    }

    int pop() {
      DFAKE_SCOPED_LOCK(push_pop_);
      return 0;
    }

   private:
    DFAKE_MUTEX(push_pop_);

    DISALLOW_COPY_AND_ASSIGN(NonThreadSafeQueue);
  };

  class QueueUser : public base::DelegateSimpleThread::Delegate {
   public:
    explicit QueueUser(NonThreadSafeQueue& queue)
        : queue_(queue) {}

    virtual void Run() {
      queue_.push(0);
      queue_.pop();
    }

   private:
    NonThreadSafeQueue& queue_;
  };

  AssertReporter* local_reporter = new AssertReporter();

  NonThreadSafeQueue queue(local_reporter);

  QueueUser queue_user_a(queue);
  QueueUser queue_user_b(queue);

  base::DelegateSimpleThread thread_a(&queue_user_a, "queue_user_thread_a");
  base::DelegateSimpleThread thread_b(&queue_user_b, "queue_user_thread_b");

  thread_a.Start();
  thread_b.Start();

  thread_a.Join();
  thread_b.Join();

#if !defined(NDEBUG)
  EXPECT_TRUE(local_reporter->fail_state());
#else
  EXPECT_FALSE(local_reporter->fail_state());
#endif
}

TEST(ThreadCollisionTest, MTSynchedScopedBookCriticalSectionTest) {
  // Queue with a 5 seconds push execution time, hopefuly the two used threads
  // in the test will enter the push at same time.
  class NonThreadSafeQueue {
   public:
    explicit NonThreadSafeQueue(base::AsserterBase* asserter)
#if !defined(NDEBUG)
        : push_pop_(asserter)
#endif
    { }

    void push(int value) {
      DFAKE_SCOPED_LOCK(push_pop_);
      PlatformThread::Sleep(5000);
    }

    int pop() {
      DFAKE_SCOPED_LOCK(push_pop_);
      return 0;
    }

   private:
    DFAKE_MUTEX(push_pop_);

    DISALLOW_COPY_AND_ASSIGN(NonThreadSafeQueue);
  };

  // This time the QueueUser class protects the non thread safe queue with
  // a lock.
  class QueueUser : public base::DelegateSimpleThread::Delegate {
   public:
    QueueUser(NonThreadSafeQueue& queue, Lock& lock)
        : queue_(queue),
          lock_(lock) {}

    virtual void Run() {
      {
        AutoLock auto_lock(lock_);
        queue_.push(0);
      }
      {
        AutoLock auto_lock(lock_);
        queue_.pop();
      }
    }
   private:
    NonThreadSafeQueue& queue_;
    Lock& lock_;
  };

  AssertReporter* local_reporter = new AssertReporter();

  NonThreadSafeQueue queue(local_reporter);

  Lock lock;

  QueueUser queue_user_a(queue, lock);
  QueueUser queue_user_b(queue, lock);

  base::DelegateSimpleThread thread_a(&queue_user_a, "queue_user_thread_a");
  base::DelegateSimpleThread thread_b(&queue_user_b, "queue_user_thread_b");

  thread_a.Start();
  thread_b.Start();

  thread_a.Join();
  thread_b.Join();

  EXPECT_FALSE(local_reporter->fail_state());
}

TEST(ThreadCollisionTest, MTSynchedScopedRecursiveBookCriticalSectionTest) {
  // Queue with a 5 seconds push execution time, hopefuly the two used threads
  // in the test will enter the push at same time.
  class NonThreadSafeQueue {
   public:
    explicit NonThreadSafeQueue(base::AsserterBase* asserter)
#if !defined(NDEBUG)
        : push_pop_(asserter)
#endif
    { }

    void push(int) {
      DFAKE_SCOPED_RECURSIVE_LOCK(push_pop_);
      bar();
      PlatformThread::Sleep(5000);
    }

    int pop() {
      DFAKE_SCOPED_RECURSIVE_LOCK(push_pop_);
      return 0;
    }

    void bar() {
      DFAKE_SCOPED_RECURSIVE_LOCK(push_pop_);
    }

   private:
    DFAKE_MUTEX(push_pop_);

    DISALLOW_COPY_AND_ASSIGN(NonThreadSafeQueue);
  };

  // This time the QueueUser class protects the non thread safe queue with
  // a lock.
  class QueueUser : public base::DelegateSimpleThread::Delegate {
   public:
    QueueUser(NonThreadSafeQueue& queue, Lock& lock)
        : queue_(queue),
          lock_(lock) {}

    virtual void Run() {
      {
        AutoLock auto_lock(lock_);
        queue_.push(0);
      }
      {
        AutoLock auto_lock(lock_);
        queue_.bar();
      }
      {
        AutoLock auto_lock(lock_);
        queue_.pop();
      }
    }
   private:
    NonThreadSafeQueue& queue_;
    Lock& lock_;
  };

  AssertReporter* local_reporter = new AssertReporter();

  NonThreadSafeQueue queue(local_reporter);

  Lock lock;

  QueueUser queue_user_a(queue, lock);
  QueueUser queue_user_b(queue, lock);

  base::DelegateSimpleThread thread_a(&queue_user_a, "queue_user_thread_a");
  base::DelegateSimpleThread thread_b(&queue_user_b, "queue_user_thread_b");

  thread_a.Start();
  thread_b.Start();

  thread_a.Join();
  thread_b.Join();

  EXPECT_FALSE(local_reporter->fail_state());
}
<commit_msg>Fix a memory leak in release with ThreadCollisionWarner unit tests. Less than ideal #ifdef's. Review URL: http://codereview.chromium.org/19018<commit_after>// Copyright (c) 2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/compiler_specific.h"
#include "base/lock.h"
#include "base/platform_thread.h"
#include "base/simple_thread.h"
#include "base/thread_collision_warner.h"
#include "testing/gtest/include/gtest/gtest.h"

// '' : local class member function does not have a body
MSVC_PUSH_DISABLE_WARNING(4822)

namespace {

// This is the asserter used with ThreadCollisionWarner instead of the default
// DCheckAsserter. The method fail_state is used to know if a collision took
// place.
class AssertReporter : public base::AsserterBase {
 public:
  AssertReporter()
      : failed_(false) {}

  virtual void warn() {
    failed_ = true;
  }

  virtual ~AssertReporter() {}

  bool fail_state() const { return failed_; }
  void reset() { failed_ = false; }

 private:
  bool failed_;
};

}  // namespace

TEST(ThreadCollisionTest, BookCriticalSection) {
  AssertReporter* local_reporter = new AssertReporter();

  base::ThreadCollisionWarner warner(local_reporter);
  EXPECT_FALSE(local_reporter->fail_state());

  {  // Pin section.
    DFAKE_SCOPED_LOCK_THREAD_LOCKED(warner);
    EXPECT_FALSE(local_reporter->fail_state());
    {  // Pin section.
      DFAKE_SCOPED_LOCK_THREAD_LOCKED(warner);
      EXPECT_FALSE(local_reporter->fail_state());
    }
  }
}

TEST(ThreadCollisionTest, ScopedRecursiveBookCriticalSection) {
  AssertReporter* local_reporter = new AssertReporter();

  base::ThreadCollisionWarner warner(local_reporter);
  EXPECT_FALSE(local_reporter->fail_state());

  {  // Pin section.
    DFAKE_SCOPED_RECURSIVE_LOCK(warner);
    EXPECT_FALSE(local_reporter->fail_state());
    {  // Pin section again (allowed by DFAKE_SCOPED_RECURSIVE_LOCK)
      DFAKE_SCOPED_RECURSIVE_LOCK(warner);
      EXPECT_FALSE(local_reporter->fail_state());
    }  // Unpin section.
  }  // Unpin section.

  // Check that section is not pinned
  {  // Pin section.
    DFAKE_SCOPED_LOCK(warner);
    EXPECT_FALSE(local_reporter->fail_state());
  }  // Unpin section.
}

TEST(ThreadCollisionTest, ScopedBookCriticalSection) {
  AssertReporter* local_reporter = new AssertReporter();

  base::ThreadCollisionWarner warner(local_reporter);
  EXPECT_FALSE(local_reporter->fail_state());

  {  // Pin section.
    DFAKE_SCOPED_LOCK(warner);
    EXPECT_FALSE(local_reporter->fail_state());
  }  // Unpin section.

  {  // Pin section.
    DFAKE_SCOPED_LOCK(warner);
    EXPECT_FALSE(local_reporter->fail_state());
    {
      // Pin section again (not allowed by DFAKE_SCOPED_LOCK)
      DFAKE_SCOPED_LOCK(warner);
#if !defined(NDEBUG)
      EXPECT_TRUE(local_reporter->fail_state());
#else
      EXPECT_FALSE(local_reporter->fail_state());
#endif
      // Reset the status of warner for further tests.
      local_reporter->reset();
    }  // Unpin section.
  }  // Unpin section.

  {
    // Pin section.
    DFAKE_SCOPED_LOCK(warner);
    EXPECT_FALSE(local_reporter->fail_state());
  }  // Unpin section.
}

TEST(ThreadCollisionTest, MTBookCriticalSectionTest) {
  class NonThreadSafeQueue {
   public:
    explicit NonThreadSafeQueue(base::AsserterBase* asserter)
#if !defined(NDEBUG)
        : push_pop_(asserter) {
#else
    {
      delete asserter;
#endif
    }

    void push(int value) {
      DFAKE_SCOPED_LOCK_THREAD_LOCKED(push_pop_);
    }

    int pop() {
      DFAKE_SCOPED_LOCK_THREAD_LOCKED(push_pop_);
      return 0;
    }

   private:
    DFAKE_MUTEX(push_pop_);

    DISALLOW_COPY_AND_ASSIGN(NonThreadSafeQueue);
  };

  class QueueUser : public base::DelegateSimpleThread::Delegate {
   public:
    explicit QueueUser(NonThreadSafeQueue& queue)
        : queue_(queue) {}

    virtual void Run() {
      queue_.push(0);
      queue_.pop();
    }

   private:
    NonThreadSafeQueue& queue_;
  };

  AssertReporter* local_reporter = new AssertReporter();

  NonThreadSafeQueue queue(local_reporter);

  QueueUser queue_user_a(queue);
  QueueUser queue_user_b(queue);

  base::DelegateSimpleThread thread_a(&queue_user_a, "queue_user_thread_a");
  base::DelegateSimpleThread thread_b(&queue_user_b, "queue_user_thread_b");

  thread_a.Start();
  thread_b.Start();

  thread_a.Join();
  thread_b.Join();

#if !defined(NDEBUG)
  EXPECT_TRUE(local_reporter->fail_state());
#else
  EXPECT_FALSE(local_reporter->fail_state());
#endif
}

TEST(ThreadCollisionTest, MTScopedBookCriticalSectionTest) {
  // Queue with a 5 seconds push execution time, hopefuly the two used threads
  // in the test will enter the push at same time.
  class NonThreadSafeQueue {
   public:
    explicit NonThreadSafeQueue(base::AsserterBase* asserter)
#if !defined(NDEBUG)
        : push_pop_(asserter) {
#else
    {
      delete asserter;
#endif
    }

    void push(int value) {
      DFAKE_SCOPED_LOCK(push_pop_);
      PlatformThread::Sleep(5000);
    }

    int pop() {
      DFAKE_SCOPED_LOCK(push_pop_);
      return 0;
    }

   private:
    DFAKE_MUTEX(push_pop_);

    DISALLOW_COPY_AND_ASSIGN(NonThreadSafeQueue);
  };

  class QueueUser : public base::DelegateSimpleThread::Delegate {
   public:
    explicit QueueUser(NonThreadSafeQueue& queue)
        : queue_(queue) {}

    virtual void Run() {
      queue_.push(0);
      queue_.pop();
    }

   private:
    NonThreadSafeQueue& queue_;
  };

  AssertReporter* local_reporter = new AssertReporter();

  NonThreadSafeQueue queue(local_reporter);

  QueueUser queue_user_a(queue);
  QueueUser queue_user_b(queue);

  base::DelegateSimpleThread thread_a(&queue_user_a, "queue_user_thread_a");
  base::DelegateSimpleThread thread_b(&queue_user_b, "queue_user_thread_b");

  thread_a.Start();
  thread_b.Start();

  thread_a.Join();
  thread_b.Join();

#if !defined(NDEBUG)
  EXPECT_TRUE(local_reporter->fail_state());
#else
  EXPECT_FALSE(local_reporter->fail_state());
#endif
}

TEST(ThreadCollisionTest, MTSynchedScopedBookCriticalSectionTest) {
  // Queue with a 5 seconds push execution time, hopefuly the two used threads
  // in the test will enter the push at same time.
  class NonThreadSafeQueue {
   public:
    explicit NonThreadSafeQueue(base::AsserterBase* asserter)
#if !defined(NDEBUG)
        : push_pop_(asserter) {
#else
    {
      delete asserter;
#endif
    }

    void push(int value) {
      DFAKE_SCOPED_LOCK(push_pop_);
      PlatformThread::Sleep(5000);
    }

    int pop() {
      DFAKE_SCOPED_LOCK(push_pop_);
      return 0;
    }

   private:
    DFAKE_MUTEX(push_pop_);

    DISALLOW_COPY_AND_ASSIGN(NonThreadSafeQueue);
  };

  // This time the QueueUser class protects the non thread safe queue with
  // a lock.
  class QueueUser : public base::DelegateSimpleThread::Delegate {
   public:
    QueueUser(NonThreadSafeQueue& queue, Lock& lock)
        : queue_(queue),
          lock_(lock) {}

    virtual void Run() {
      {
        AutoLock auto_lock(lock_);
        queue_.push(0);
      }
      {
        AutoLock auto_lock(lock_);
        queue_.pop();
      }
    }
   private:
    NonThreadSafeQueue& queue_;
    Lock& lock_;
  };

  AssertReporter* local_reporter = new AssertReporter();

  NonThreadSafeQueue queue(local_reporter);

  Lock lock;

  QueueUser queue_user_a(queue, lock);
  QueueUser queue_user_b(queue, lock);

  base::DelegateSimpleThread thread_a(&queue_user_a, "queue_user_thread_a");
  base::DelegateSimpleThread thread_b(&queue_user_b, "queue_user_thread_b");

  thread_a.Start();
  thread_b.Start();

  thread_a.Join();
  thread_b.Join();

  EXPECT_FALSE(local_reporter->fail_state());
}

TEST(ThreadCollisionTest, MTSynchedScopedRecursiveBookCriticalSectionTest) {
  // Queue with a 5 seconds push execution time, hopefuly the two used threads
  // in the test will enter the push at same time.
  class NonThreadSafeQueue {
   public:
    explicit NonThreadSafeQueue(base::AsserterBase* asserter)
#if !defined(NDEBUG)
        : push_pop_(asserter) {
#else
    {
      delete asserter;
#endif
    }

    void push(int) {
      DFAKE_SCOPED_RECURSIVE_LOCK(push_pop_);
      bar();
      PlatformThread::Sleep(5000);
    }

    int pop() {
      DFAKE_SCOPED_RECURSIVE_LOCK(push_pop_);
      return 0;
    }

    void bar() {
      DFAKE_SCOPED_RECURSIVE_LOCK(push_pop_);
    }

   private:
    DFAKE_MUTEX(push_pop_);

    DISALLOW_COPY_AND_ASSIGN(NonThreadSafeQueue);
  };

  // This time the QueueUser class protects the non thread safe queue with
  // a lock.
  class QueueUser : public base::DelegateSimpleThread::Delegate {
   public:
    QueueUser(NonThreadSafeQueue& queue, Lock& lock)
        : queue_(queue),
          lock_(lock) {}

    virtual void Run() {
      {
        AutoLock auto_lock(lock_);
        queue_.push(0);
      }
      {
        AutoLock auto_lock(lock_);
        queue_.bar();
      }
      {
        AutoLock auto_lock(lock_);
        queue_.pop();
      }
    }
   private:
    NonThreadSafeQueue& queue_;
    Lock& lock_;
  };

  AssertReporter* local_reporter = new AssertReporter();

  NonThreadSafeQueue queue(local_reporter);

  Lock lock;

  QueueUser queue_user_a(queue, lock);
  QueueUser queue_user_b(queue, lock);

  base::DelegateSimpleThread thread_a(&queue_user_a, "queue_user_thread_a");
  base::DelegateSimpleThread thread_b(&queue_user_b, "queue_user_thread_b");

  thread_a.Start();
  thread_b.Start();

  thread_a.Join();
  thread_b.Join();

  EXPECT_FALSE(local_reporter->fail_state());
}
<|endoftext|>


<commit_before>// Scintilla source code edit control
/** @file CallTip.cxx
 ** Code for displaying call tips.
 **/
// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>

#include "Platform.h"

#include "Scintilla.h"
#include "CallTip.h"

CallTip::CallTip() {
	wCallTip = 0;
	inCallTipMode = false;
	posStartCallTip = 0;
	val = 0;
	rectUp = PRectangle(0,0,0,0);
	rectDown = PRectangle(0,0,0,0);
	lineHeight = 1;
	startHighlight = 0;
	endHighlight = 0;

	colourBG.desired = ColourDesired(0xff, 0xff, 0xff);
	colourUnSel.desired = ColourDesired(0x80, 0x80, 0x80);
	colourSel.desired = ColourDesired(0, 0, 0x80);
	colourShade.desired = ColourDesired(0, 0, 0);
	colourLight.desired = ColourDesired(0xc0, 0xc0, 0xc0);
}

CallTip::~CallTip() {
	font.Release();
	wCallTip.Destroy();
	delete []val;
	val = 0;
}

const int widthArrow = 14;

void CallTip::RefreshColourPalette(Palette &pal, bool want) {
	pal.WantFind(colourBG, want);
	pal.WantFind(colourUnSel, want);
	pal.WantFind(colourSel, want);
	pal.WantFind(colourShade, want);
	pal.WantFind(colourLight, want);
}

static bool IsArrowCharacter(char ch) {
	return (ch == 0) || (ch == '\001') || (ch == '\002');
}

void CallTip::DrawChunk(Surface *surface, int &x, const char *s,
	int posStart, int posEnd, int ytext, PRectangle rcClient,
	bool highlight, bool draw) {
	s += posStart;
	int len = posEnd - posStart;
	int maxEnd = 0;
	int ends[10];
	for (int i=0;i<len;i++) {
		if (IsArrowCharacter(s[i])) {
			if (i > 0)
				ends[maxEnd++] = i;
			ends[maxEnd++] = i+1;
		}
	}
	ends[maxEnd++] = len;
	int startSeg = 0;
	int xEnd;
	for (int seg = 0; seg<maxEnd; seg++) {
		int endSeg = ends[seg];
		if (endSeg > startSeg) {
			if (IsArrowCharacter(s[startSeg])) {
				xEnd = x + widthArrow;
				offsetMain = xEnd;
				rcClient.left = x;
				rcClient.right = xEnd;
				if (draw) {
					const int halfWidth = widthArrow / 2 - 3;
					const int centreX = x + widthArrow / 2 - 1;
					const int centreY = (rcClient.top + rcClient.bottom) / 2;
					surface->FillRectangle(rcClient, colourBG.allocated);
					PRectangle rcClientInner(rcClient.left+1, rcClient.top+1, rcClient.right-2, rcClient.bottom-1);
					surface->FillRectangle(rcClientInner, colourUnSel.allocated);

					if (s[startSeg] == '\001') {
						// Up arrow
						Point pts[] = {
    						Point(centreX - halfWidth, centreY + halfWidth / 2),
    						Point(centreX + halfWidth, centreY + halfWidth / 2),
    						Point(centreX, centreY - halfWidth + halfWidth / 2),
						};
						surface->Polygon(pts, sizeof(pts) / sizeof(pts[0]),
                 						colourBG.allocated, colourBG.allocated);
					} else {
						// Down arrow
						Point pts[] = {
    						Point(centreX - halfWidth, centreY - halfWidth / 2),
    						Point(centreX + halfWidth, centreY - halfWidth / 2),
    						Point(centreX, centreY + halfWidth - halfWidth / 2),
						};
						surface->Polygon(pts, sizeof(pts) / sizeof(pts[0]),
                 						colourBG.allocated, colourBG.allocated);
					}
				} else {
					if (s[startSeg] == '\001') {
						rectUp = rcClient;
					} else {
						rectDown = rcClient;
					}
				}
			} else {
				xEnd = x + surface->WidthText(font, s+startSeg, endSeg - startSeg);
				if (draw) {
					rcClient.left = x;
					rcClient.right = xEnd;
					surface->DrawTextNoClip(rcClient, font, ytext,
										s+startSeg, endSeg - startSeg,
										highlight ? colourSel.allocated : colourUnSel.allocated,
										colourBG.allocated);
				}
			}
			x = xEnd;
			startSeg = endSeg;
		}
	}
}

int CallTip::PaintContents(Surface *surfaceWindow, bool draw) {
	PRectangle rcClientPos = wCallTip.GetClientPosition();
	PRectangle rcClientSize(0, 0, rcClientPos.right - rcClientPos.left,
	                        rcClientPos.bottom - rcClientPos.top);
	PRectangle rcClient(1, 1, rcClientSize.right - 1, rcClientSize.bottom - 1);

	// To make a nice small call tip window, it is only sized to fit most normal characters without accents
	int ascent = surfaceWindow->Ascent(font) - surfaceWindow->InternalLeading(font);

	// For each line...
	// Draw the definition in three parts: before highlight, highlighted, after highlight
	int ytext = rcClient.top + ascent + 1;
	rcClient.bottom = ytext + surfaceWindow->Descent(font) + 1;
	char *chunkVal = val;
	bool moreChunks = true;
	int maxWidth = 0;
	while (moreChunks) {
		char *chunkEnd = strchr(chunkVal, '\n');
		if (chunkEnd == NULL) {
			chunkEnd = chunkVal + strlen(chunkVal);
			moreChunks = false;
		}
		int chunkOffset = chunkVal - val;
		int chunkLength = chunkEnd - chunkVal;
		int chunkEndOffset = chunkOffset + chunkLength;
		int thisStartHighlight = Platform::Maximum(startHighlight, chunkOffset);
		thisStartHighlight = Platform::Minimum(thisStartHighlight, chunkEndOffset);
		thisStartHighlight -= chunkOffset;
		int thisEndHighlight = Platform::Maximum(endHighlight, chunkOffset);
		thisEndHighlight = Platform::Minimum(thisEndHighlight, chunkEndOffset);
		thisEndHighlight -= chunkOffset;
		rcClient.top = ytext - ascent - 1;

		int x = 5;

		DrawChunk(surfaceWindow, x, chunkVal, 0, thisStartHighlight,
			ytext, rcClient, false, draw);
		DrawChunk(surfaceWindow, x, chunkVal, thisStartHighlight, thisEndHighlight,
			ytext, rcClient, true, draw);
		DrawChunk(surfaceWindow, x, chunkVal, thisEndHighlight, chunkLength,
			ytext, rcClient, false, draw);

		chunkVal = chunkEnd + 1;
		ytext += lineHeight;
		rcClient.bottom += lineHeight;
		maxWidth = Platform::Maximum(maxWidth, x);
	}
	return maxWidth;
}

void CallTip::PaintCT(Surface *surfaceWindow) {
	if (!val)
		return;
	PRectangle rcClientPos = wCallTip.GetClientPosition();
	PRectangle rcClientSize(0, 0, rcClientPos.right - rcClientPos.left,
	                        rcClientPos.bottom - rcClientPos.top);
	PRectangle rcClient(1, 1, rcClientSize.right - 1, rcClientSize.bottom - 1);

	surfaceWindow->FillRectangle(rcClient, colourBG.allocated);

	offsetMain = 5;
	PaintContents(surfaceWindow, true);

	// Draw a raised border around the edges of the window
	surfaceWindow->MoveTo(0, rcClientSize.bottom - 1);
	surfaceWindow->PenColour(colourShade.allocated);
	surfaceWindow->LineTo(rcClientSize.right - 1, rcClientSize.bottom - 1);
	surfaceWindow->LineTo(rcClientSize.right - 1, 0);
	surfaceWindow->PenColour(colourLight.allocated);
	surfaceWindow->LineTo(0, 0);
	surfaceWindow->LineTo(0, rcClientSize.bottom - 1);
}

void CallTip::MouseClick(Point pt) {
	clickPlace = 0;
	if (rectUp.Contains(pt))
		clickPlace = 1;
	if (rectDown.Contains(pt))
		clickPlace = 2;
}

PRectangle CallTip::CallTipStart(int pos, Point pt, const char *defn,
                                 const char *faceName, int size,
                                 int codePage_, int characterSet, Window &wParent) {
	clickPlace = 0;
	if (val)
		delete []val;
	val = new char[strlen(defn) + 1];
	if (!val)
		return PRectangle();
	strcpy(val, defn);
	codePage = codePage_;
	Surface *surfaceMeasure = Surface::Allocate();
	if (!surfaceMeasure)
		return PRectangle();
	surfaceMeasure->Init(wParent.GetID());
	surfaceMeasure->SetUnicodeMode(SC_CP_UTF8 == codePage);
	surfaceMeasure->SetDBCSMode(codePage);
	startHighlight = 0;
	endHighlight = 0;
	inCallTipMode = true;
	posStartCallTip = pos;
	int deviceHeight = surfaceMeasure->DeviceHeightFont(size);
	font.Create(faceName, characterSet, deviceHeight, false, false);
	// Look for multiple lines in the text
	// Only support \n here - simply means container must avoid \r!
	int numLines = 1;
	const char *newline;
	const char *look = val;
	rectUp = PRectangle(0,0,0,0);
	rectDown = PRectangle(0,0,0,0);
	offsetMain = 5;
	int width = PaintContents(surfaceMeasure, false) + 5;
	while ((newline = strchr(look, '\n')) != NULL) {
		look = newline + 1;
		numLines++;
	}
	lineHeight = surfaceMeasure->Height(font);
	// Extra line for border and an empty line at top and bottom
	int height = lineHeight * numLines - surfaceMeasure->InternalLeading(font) + 2 + 2;
	delete surfaceMeasure;
	return PRectangle(pt.x - offsetMain, pt.y + 1, pt.x + width - offsetMain, pt.y + 1 + height);
}

void CallTip::CallTipCancel() {
	inCallTipMode = false;
	if (wCallTip.Created()) {
		wCallTip.Destroy();
	}
}

void CallTip::SetHighlight(int start, int end) {
	// Avoid flashing by checking something has really changed
	if ((start != startHighlight) || (end != endHighlight)) {
		startHighlight = start;
		endHighlight = end;
		if (wCallTip.Created()) {
			wCallTip.InvalidateAll();
		}
	}
}
<commit_msg>Ensure down arrow works for initial call.<commit_after>// Scintilla source code edit control
/** @file CallTip.cxx
 ** Code for displaying call tips.
 **/
// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>

#include "Platform.h"

#include "Scintilla.h"
#include "CallTip.h"

CallTip::CallTip() {
	wCallTip = 0;
	inCallTipMode = false;
	posStartCallTip = 0;
	val = 0;
	rectUp = PRectangle(0,0,0,0);
	rectDown = PRectangle(0,0,0,0);
	lineHeight = 1;
	startHighlight = 0;
	endHighlight = 0;

	colourBG.desired = ColourDesired(0xff, 0xff, 0xff);
	colourUnSel.desired = ColourDesired(0x80, 0x80, 0x80);
	colourSel.desired = ColourDesired(0, 0, 0x80);
	colourShade.desired = ColourDesired(0, 0, 0);
	colourLight.desired = ColourDesired(0xc0, 0xc0, 0xc0);
}

CallTip::~CallTip() {
	font.Release();
	wCallTip.Destroy();
	delete []val;
	val = 0;
}

const int widthArrow = 14;

void CallTip::RefreshColourPalette(Palette &pal, bool want) {
	pal.WantFind(colourBG, want);
	pal.WantFind(colourUnSel, want);
	pal.WantFind(colourSel, want);
	pal.WantFind(colourShade, want);
	pal.WantFind(colourLight, want);
}

static bool IsArrowCharacter(char ch) {
	return (ch == 0) || (ch == '\001') || (ch == '\002');
}

void CallTip::DrawChunk(Surface *surface, int &x, const char *s,
	int posStart, int posEnd, int ytext, PRectangle rcClient,
	bool highlight, bool draw) {
	s += posStart;
	int len = posEnd - posStart;
	int maxEnd = 0;
	int ends[10];
	for (int i=0;i<len;i++) {
		if (IsArrowCharacter(s[i])) {
			if (i > 0)
				ends[maxEnd++] = i;
			ends[maxEnd++] = i+1;
		}
	}
	ends[maxEnd++] = len;
	int startSeg = 0;
	int xEnd;
	for (int seg = 0; seg<maxEnd; seg++) {
		int endSeg = ends[seg];
		if (endSeg > startSeg) {
			if (IsArrowCharacter(s[startSeg])) {
				xEnd = x + widthArrow;
				offsetMain = xEnd;
				rcClient.left = x;
				rcClient.right = xEnd;
				if (draw) {
					const int halfWidth = widthArrow / 2 - 3;
					const int centreX = x + widthArrow / 2 - 1;
					const int centreY = (rcClient.top + rcClient.bottom) / 2;
					surface->FillRectangle(rcClient, colourBG.allocated);
					PRectangle rcClientInner(rcClient.left+1, rcClient.top+1, rcClient.right-2, rcClient.bottom-1);
					surface->FillRectangle(rcClientInner, colourUnSel.allocated);

					if (s[startSeg] == '\001') {
						// Up arrow
						Point pts[] = {
    						Point(centreX - halfWidth, centreY + halfWidth / 2),
    						Point(centreX + halfWidth, centreY + halfWidth / 2),
    						Point(centreX, centreY - halfWidth + halfWidth / 2),
						};
						surface->Polygon(pts, sizeof(pts) / sizeof(pts[0]),
                 						colourBG.allocated, colourBG.allocated);
					} else {
						// Down arrow
						Point pts[] = {
    						Point(centreX - halfWidth, centreY - halfWidth / 2),
    						Point(centreX + halfWidth, centreY - halfWidth / 2),
    						Point(centreX, centreY + halfWidth - halfWidth / 2),
						};
						surface->Polygon(pts, sizeof(pts) / sizeof(pts[0]),
                 						colourBG.allocated, colourBG.allocated);
					}
				}
				if (s[startSeg] == '\001') {
					rectUp = rcClient;
				} else if (s[startSeg] == '\002') {
					rectDown = rcClient;
				}
			} else {
				xEnd = x + surface->WidthText(font, s+startSeg, endSeg - startSeg);
				if (draw) {
					rcClient.left = x;
					rcClient.right = xEnd;
					surface->DrawTextNoClip(rcClient, font, ytext,
										s+startSeg, endSeg - startSeg,
										highlight ? colourSel.allocated : colourUnSel.allocated,
										colourBG.allocated);
				}
			}
			x = xEnd;
			startSeg = endSeg;
		}
	}
}

int CallTip::PaintContents(Surface *surfaceWindow, bool draw) {
	PRectangle rcClientPos = wCallTip.GetClientPosition();
	PRectangle rcClientSize(0, 0, rcClientPos.right - rcClientPos.left,
	                        rcClientPos.bottom - rcClientPos.top);
	PRectangle rcClient(1, 1, rcClientSize.right - 1, rcClientSize.bottom - 1);

	// To make a nice small call tip window, it is only sized to fit most normal characters without accents
	int ascent = surfaceWindow->Ascent(font) - surfaceWindow->InternalLeading(font);

	// For each line...
	// Draw the definition in three parts: before highlight, highlighted, after highlight
	int ytext = rcClient.top + ascent + 1;
	rcClient.bottom = ytext + surfaceWindow->Descent(font) + 1;
	char *chunkVal = val;
	bool moreChunks = true;
	int maxWidth = 0;
	while (moreChunks) {
		char *chunkEnd = strchr(chunkVal, '\n');
		if (chunkEnd == NULL) {
			chunkEnd = chunkVal + strlen(chunkVal);
			moreChunks = false;
		}
		int chunkOffset = chunkVal - val;
		int chunkLength = chunkEnd - chunkVal;
		int chunkEndOffset = chunkOffset + chunkLength;
		int thisStartHighlight = Platform::Maximum(startHighlight, chunkOffset);
		thisStartHighlight = Platform::Minimum(thisStartHighlight, chunkEndOffset);
		thisStartHighlight -= chunkOffset;
		int thisEndHighlight = Platform::Maximum(endHighlight, chunkOffset);
		thisEndHighlight = Platform::Minimum(thisEndHighlight, chunkEndOffset);
		thisEndHighlight -= chunkOffset;
		rcClient.top = ytext - ascent - 1;

		int x = 5;

		DrawChunk(surfaceWindow, x, chunkVal, 0, thisStartHighlight,
			ytext, rcClient, false, draw);
		DrawChunk(surfaceWindow, x, chunkVal, thisStartHighlight, thisEndHighlight,
			ytext, rcClient, true, draw);
		DrawChunk(surfaceWindow, x, chunkVal, thisEndHighlight, chunkLength,
			ytext, rcClient, false, draw);

		chunkVal = chunkEnd + 1;
		ytext += lineHeight;
		rcClient.bottom += lineHeight;
		maxWidth = Platform::Maximum(maxWidth, x);
	}
	return maxWidth;
}

void CallTip::PaintCT(Surface *surfaceWindow) {
	if (!val)
		return;
	PRectangle rcClientPos = wCallTip.GetClientPosition();
	PRectangle rcClientSize(0, 0, rcClientPos.right - rcClientPos.left,
	                        rcClientPos.bottom - rcClientPos.top);
	PRectangle rcClient(1, 1, rcClientSize.right - 1, rcClientSize.bottom - 1);

	surfaceWindow->FillRectangle(rcClient, colourBG.allocated);

	offsetMain = 5;
	PaintContents(surfaceWindow, true);

	// Draw a raised border around the edges of the window
	surfaceWindow->MoveTo(0, rcClientSize.bottom - 1);
	surfaceWindow->PenColour(colourShade.allocated);
	surfaceWindow->LineTo(rcClientSize.right - 1, rcClientSize.bottom - 1);
	surfaceWindow->LineTo(rcClientSize.right - 1, 0);
	surfaceWindow->PenColour(colourLight.allocated);
	surfaceWindow->LineTo(0, 0);
	surfaceWindow->LineTo(0, rcClientSize.bottom - 1);
}

void CallTip::MouseClick(Point pt) {
	clickPlace = 0;
	if (rectUp.Contains(pt))
		clickPlace = 1;
	if (rectDown.Contains(pt))
		clickPlace = 2;
}

PRectangle CallTip::CallTipStart(int pos, Point pt, const char *defn,
                                 const char *faceName, int size,
                                 int codePage_, int characterSet, Window &wParent) {
	clickPlace = 0;
	if (val)
		delete []val;
	val = new char[strlen(defn) + 1];
	if (!val)
		return PRectangle();
	strcpy(val, defn);
	codePage = codePage_;
	Surface *surfaceMeasure = Surface::Allocate();
	if (!surfaceMeasure)
		return PRectangle();
	surfaceMeasure->Init(wParent.GetID());
	surfaceMeasure->SetUnicodeMode(SC_CP_UTF8 == codePage);
	surfaceMeasure->SetDBCSMode(codePage);
	startHighlight = 0;
	endHighlight = 0;
	inCallTipMode = true;
	posStartCallTip = pos;
	int deviceHeight = surfaceMeasure->DeviceHeightFont(size);
	font.Create(faceName, characterSet, deviceHeight, false, false);
	// Look for multiple lines in the text
	// Only support \n here - simply means container must avoid \r!
	int numLines = 1;
	const char *newline;
	const char *look = val;
	rectUp = PRectangle(0,0,0,0);
	rectDown = PRectangle(0,0,0,0);
	offsetMain = 5;
	int width = PaintContents(surfaceMeasure, false) + 5;
	while ((newline = strchr(look, '\n')) != NULL) {
		look = newline + 1;
		numLines++;
	}
	lineHeight = surfaceMeasure->Height(font);
	// Extra line for border and an empty line at top and bottom
	int height = lineHeight * numLines - surfaceMeasure->InternalLeading(font) + 2 + 2;
	delete surfaceMeasure;
	return PRectangle(pt.x - offsetMain, pt.y + 1, pt.x + width - offsetMain, pt.y + 1 + height);
}

void CallTip::CallTipCancel() {
	inCallTipMode = false;
	if (wCallTip.Created()) {
		wCallTip.Destroy();
	}
}

void CallTip::SetHighlight(int start, int end) {
	// Avoid flashing by checking something has really changed
	if ((start != startHighlight) || (end != endHighlight)) {
		startHighlight = start;
		endHighlight = end;
		if (wCallTip.Created()) {
			wCallTip.InvalidateAll();
		}
	}
}
<|endoftext|>