<commit_before>/***************************************************************************
**
** Copyright (C) 2013 Research In Motion
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtBluetooth module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qbluetoothtransferreply_qnx_p.h"
#include "qbluetoothaddress.h"

#include "qbluetoothtransferreply.h"

#include <QFuture>
#include <QFutureWatcher>
#include <QtConcurrentRun>

#include "qnx/ppshelpers_p.h"
#include <QSocketNotifier>

#include <QtCore/private/qcore_unix_p.h>

#include <QTime>

//static const QLatin1String agentPath("/shared/tmp/opp");

QT_BEGIN_NAMESPACE_BLUETOOTH

QBluetoothTransferReplyQnx::QBluetoothTransferReplyQnx(QIODevice *input, const QBluetoothTransferRequest &request,
                                                       QObject *parent)
:   QBluetoothTransferReply(parent), tempfile(0), source(input),
    m_running(false), m_finished(false),
    m_error(QBluetoothTransferReply::NoError), m_errorStr()
{
    ppsRegisterControl();
    //qsrand(QTime::currentTime().msec());
    //m_agent_path = agentPath;
    //m_agent_path.append(QString::fromLatin1("/%1").arg(qrand()));
    ppsRegisterForEvent("opp_update", this);
    ppsRegisterForEvent("opp_complete", this);
    ppsRegisterForEvent("opp_cancelled", this);

    QMetaObject::invokeMethod(this, "start", Qt::QueuedConnection);
}

/*!
    Destroys the QBluetoothTransferReply object.
*/
QBluetoothTransferReplyQnx::~QBluetoothTransferReplyQnx()
{
    ppsUnregisterControl(this);
}

bool QBluetoothTransferReplyQnx::start()
{
    m_running = true;
    m_error = QBluetoothTransferReply::NoError;
    m_errorStr = QString();

    QFile *file = qobject_cast<QFile *>(source);

    if (!file){
//        tempfile = new QTemporaryFile(this );
//        tempfile->open();

//        QFutureWatcher<bool> *watcher = new QFutureWatcher<bool>();
//        QObject::connect(watcher, SIGNAL(finished()), this, SLOT(copyDone()));

//        QFuture<bool> results = QtConcurrent::run(QBluetoothTransferReplyQnx::copyToTempFile, tempfile, source);
//        watcher->setFuture(results);
        //QTemporaryFile does not work properly yet
        m_error = QBluetoothTransferReply::UnknownError;
        m_finished = true;
        m_running = false;
        Q_EMIT finished(this);

    } else {
        startOPP(file->fileName());
    }
    return true;
}

bool QBluetoothTransferReplyQnx::copyToTempFile(QIODevice *to, QIODevice *from)
{
    char *block = new char[4096];
    int size;

    while ((size = from->read(block, 4096))) {
        if (size != to->write(block, size))
            return false;
    }

    delete[] block;
    return true;
}

void QBluetoothTransferReplyQnx::copyDone()
{
    qBBBluetoothDebug() << "Copy done";
    startOPP(tempfile->fileName());
    QObject::sender()->deleteLater();
}

void QBluetoothTransferReplyQnx::startOPP(QString filename)
{
    qBBBluetoothDebug() << "Sending Push object command";
    ppsSendOpp("push_object", filename.toUtf8(), m_address, this);
}

QBluetoothTransferReply::TransferError QBluetoothTransferReplyQnx::error() const
{
    return m_error;
}

QString QBluetoothTransferReplyQnx::errorString() const
{
    return m_errorStr;
}

void QBluetoothTransferReplyQnx::controlReply(ppsResult result)
{
    if (!result.errorMsg.isEmpty()) {
        m_errorStr = result.errorMsg;
        m_error = QBluetoothTransferReply::UnknownError;
    }
}

void QBluetoothTransferReplyQnx::controlEvent(ppsResult result)
{
    if (result.msg == QStringLiteral("opp_cancelled")) {
        qBBBluetoothDebug() << "opp cancelled" << result.errorMsg << result.error;
        if (m_running)
            return;
        m_finished = true;
        m_running = false;
//        bool ok;
//        int reason = result.dat.at(result.dat.indexOf(QStringLiteral("reason")) + 1).toInt(&ok);
//        if (ok) {
//            switch (reason) {
//            case 1: m_error = QBluetoothTransferReply::UserCanceledTransferError;
//            case 3: m_error = QBluetoothTransferReply::UserCanceledTransferError;
//            }
//        } else {
        m_errorStr = result.errorMsg;
        m_error = QBluetoothTransferReply::UnknownError;
//      }
        Q_EMIT finished(this);
    } else if (result.msg == QStringLiteral("opp_update")) {
        bool ok;
        int sentBytes = result.dat.at(result.dat.indexOf(QStringLiteral("sent")) + 1).toInt(&ok);
        if (!ok)
            return;
        int totalBytes = result.dat.at(result.dat.indexOf(QStringLiteral("total")) + 1).toInt(&ok);
        if (!ok)
            return;
        qBBBluetoothDebug() << "opp update" << sentBytes << totalBytes;
        Q_EMIT uploadProgress(sentBytes, totalBytes);
    } else if (result.msg == QStringLiteral("opp_complete")) {
        qBBBluetoothDebug() << "opp complete";
        m_finished = true;
        m_running = false;
        Q_EMIT finished(this);
    }
}

/*!
    Returns true if this reply has finished; otherwise returns false.
*/
bool QBluetoothTransferReplyQnx::isFinished() const
{
    return m_finished;
}

/*!
    Returns true if this reply is running; otherwise returns false.
*/
bool QBluetoothTransferReplyQnx::isRunning() const
{
    return m_running;
}

void QBluetoothTransferReplyQnx::abort()
{
    //not supported yet
}

#include "moc_qbluetoothtransferreply_qnx_p.cpp"

QT_END_NAMESPACE_BLUETOOTH
<commit_msg>QNX: Fix Compilation error and compiler warnings<commit_after>/***************************************************************************
**
** Copyright (C) 2013 Research In Motion
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtBluetooth module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qbluetoothtransferreply_qnx_p.h"
#include "qbluetoothaddress.h"

#include "qbluetoothtransferreply.h"

#include <QFuture>
#include <QFutureWatcher>
#include <QtConcurrentRun>

#include "qnx/ppshelpers_p.h"
#include <QSocketNotifier>

#include <QtCore/private/qcore_unix_p.h>

#include <QTime>

//static const QLatin1String agentPath("/shared/tmp/opp");

QT_BEGIN_NAMESPACE_BLUETOOTH

QBluetoothTransferReplyQnx::QBluetoothTransferReplyQnx(QIODevice *input, const QBluetoothTransferRequest &request,
                                                       QObject *parent)
:   QBluetoothTransferReply(parent), tempfile(0), source(input),
    m_running(false), m_finished(false),
    m_error(QBluetoothTransferReply::NoError), m_errorStr()
{
    ppsRegisterControl();
    //qsrand(QTime::currentTime().msec());
    //m_agent_path = agentPath;
    //m_agent_path.append(QString::fromLatin1("/%1").arg(qrand()));
    ppsRegisterForEvent(QStringLiteral("opp_update"), this);
    ppsRegisterForEvent(QStringLiteral("opp_complete"), this);
    ppsRegisterForEvent(QStringLiteral("opp_cancelled"), this);

    QMetaObject::invokeMethod(this, "start", Qt::QueuedConnection);
}

/*!
    Destroys the QBluetoothTransferReply object.
*/
QBluetoothTransferReplyQnx::~QBluetoothTransferReplyQnx()
{
    ppsUnregisterControl(this);
}

bool QBluetoothTransferReplyQnx::start()
{
    m_running = true;
    m_error = QBluetoothTransferReply::NoError;
    m_errorStr = QString();

    QFile *file = qobject_cast<QFile *>(source);

    if (!file){
//        tempfile = new QTemporaryFile(this );
//        tempfile->open();

//        QFutureWatcher<bool> *watcher = new QFutureWatcher<bool>();
//        QObject::connect(watcher, SIGNAL(finished()), this, SLOT(copyDone()));

//        QFuture<bool> results = QtConcurrent::run(QBluetoothTransferReplyQnx::copyToTempFile, tempfile, source);
//        watcher->setFuture(results);
        //QTemporaryFile does not work properly yet
        m_error = QBluetoothTransferReply::UnknownError;
        m_finished = true;
        m_running = false;
        Q_EMIT finished(this);

    } else {
        startOPP(file->fileName());
    }
    return true;
}

bool QBluetoothTransferReplyQnx::copyToTempFile(QIODevice *to, QIODevice *from)
{
    char *block = new char[4096];
    int size;

    while ((size = from->read(block, 4096))) {
        if (size != to->write(block, size))
            return false;
    }

    delete[] block;
    return true;
}

void QBluetoothTransferReplyQnx::copyDone()
{
    qBBBluetoothDebug() << "Copy done";
    startOPP(tempfile->fileName());
    QObject::sender()->deleteLater();
}

void QBluetoothTransferReplyQnx::startOPP(QString filename)
{
    qBBBluetoothDebug() << "Sending Push object command";
    ppsSendOpp("push_object", filename.toUtf8(), request().address(), this);
}

QBluetoothTransferReply::TransferError QBluetoothTransferReplyQnx::error() const
{
    return m_error;
}

QString QBluetoothTransferReplyQnx::errorString() const
{
    return m_errorStr;
}

void QBluetoothTransferReplyQnx::controlReply(ppsResult result)
{
    if (!result.errorMsg.isEmpty()) {
        m_errorStr = result.errorMsg;
        m_error = QBluetoothTransferReply::UnknownError;
    }
}

void QBluetoothTransferReplyQnx::controlEvent(ppsResult result)
{
    if (result.msg == QStringLiteral("opp_cancelled")) {
        qBBBluetoothDebug() << "opp cancelled" << result.errorMsg << result.error;
        if (m_running)
            return;
        m_finished = true;
        m_running = false;
//        bool ok;
//        int reason = result.dat.at(result.dat.indexOf(QStringLiteral("reason")) + 1).toInt(&ok);
//        if (ok) {
//            switch (reason) {
//            case 1: m_error = QBluetoothTransferReply::UserCanceledTransferError;
//            case 3: m_error = QBluetoothTransferReply::UserCanceledTransferError;
//            }
//        } else {
        m_errorStr = result.errorMsg;
        m_error = QBluetoothTransferReply::UnknownError;
//      }
        Q_EMIT finished(this);
    } else if (result.msg == QStringLiteral("opp_update")) {
        bool ok;
        int sentBytes = result.dat.at(result.dat.indexOf(QStringLiteral("sent")) + 1).toInt(&ok);
        if (!ok)
            return;
        int totalBytes = result.dat.at(result.dat.indexOf(QStringLiteral("total")) + 1).toInt(&ok);
        if (!ok)
            return;
        qBBBluetoothDebug() << "opp update" << sentBytes << totalBytes;
        Q_EMIT transferProgress(sentBytes, totalBytes);
    } else if (result.msg == QStringLiteral("opp_complete")) {
        qBBBluetoothDebug() << "opp complete";
        m_finished = true;
        m_running = false;
        Q_EMIT finished(this);
    }
}

/*!
    Returns true if this reply has finished; otherwise returns false.
*/
bool QBluetoothTransferReplyQnx::isFinished() const
{
    return m_finished;
}

/*!
    Returns true if this reply is running; otherwise returns false.
*/
bool QBluetoothTransferReplyQnx::isRunning() const
{
    return m_running;
}

void QBluetoothTransferReplyQnx::abort()
{
    //not supported yet
}

#include "moc_qbluetoothtransferreply_qnx_p.cpp"

QT_END_NAMESPACE_BLUETOOTH
<|endoftext|>


<commit_before>// Filename: LinearSolver.C
// Created on 09 Sep 2003 by Boyce Griffith
//
// Copyright (c) 2002-2010, Boyce Griffith
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
//    * Redistributions of source code must retain the above copyright notice,
//      this list of conditions and the following disclaimer.
//
//    * Redistributions in binary form must reproduce the above copyright
//      notice, this list of conditions and the following disclaimer in the
//      documentation and/or other materials provided with the distribution.
//
//    * Neither the name of New York University nor the names of its
//      contributors may be used to endorse or promote products derived from
//      this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 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 "LinearSolver.h"

/////////////////////////////// INCLUDES /////////////////////////////////////

#ifndef included_IBTK_config
#include <IBTK_config.h>
#define included_IBTK_config
#endif

#ifndef included_SAMRAI_config
#include <SAMRAI_config.h>
#define included_SAMRAI_config
#endif

// IBTK INCLUDES
#include <ibtk/namespaces.h>

/////////////////////////////// NAMESPACE ////////////////////////////////////

namespace IBTK
{
/////////////////////////////// STATIC ///////////////////////////////////////

/////////////////////////////// PUBLIC ///////////////////////////////////////

LinearSolver::LinearSolver(
    const std::string& object_name,
    bool homogeneous_bc)
    : GeneralSolver(object_name, homogeneous_bc),
      d_nullspace_contains_constant_vec(false),
      d_nullspace_basis_vecs(),
      d_initial_guess_nonzero(true),
      d_rel_residual_tol(1.0e-5),
      d_abs_residual_tol(1.0e-50),
      d_max_iterations(10000),
      d_current_iterations(0),
      d_current_residual_norm(std::numeric_limits<double>::quiet_NaN())
{
    // intentionally blank
    return;
}// LinearSolver()

LinearSolver::~LinearSolver()
{
    // intentionally blank
    return;
}// ~LinearSolver()

void
LinearSolver::setNullspace(
    const bool nullspace_containsconstant_vec,
    const std::vector<Pointer<SAMRAIVectorReal<NDIM,double> > >& nullspace_basis_vecs)
{
    d_nullspace_contains_constant_vec = nullspace_containsconstant_vec;
    d_nullspace_basis_vecs = nullspace_basis_vecs;
    return;
}// setNullspace

void
LinearSolver::setInitialGuessNonzero(
    bool initial_guess_nonzero)
{
    d_initial_guess_nonzero = initial_guess_nonzero;
    return;
}// setInitialGuessNonzero

bool
LinearSolver::getNullspaceContainsConstantVector() const
{
    return d_nullspace_contains_constant_vec;
}// getNullspaceContainsConstantVector

const std::vector<Pointer<SAMRAIVectorReal<NDIM,double> > >&
LinearSolver::getNullspaceBasisVectors() const
{
    return d_nullspace_basis_vecs;
}// getNullspaceBasisVectors

bool
LinearSolver::getInitialGuessNonzero() const
{
    return d_initial_guess_nonzero;
}// getInitialGuessNonzero

void
LinearSolver::setMaxIterations(
    int max_iterations)
{
    d_max_iterations = max_iterations;
    return;
}// setMaxIterations

int
LinearSolver::getMaxIterations() const
{
    return d_max_iterations;
}// getMaxIterations

void
LinearSolver::setAbsoluteTolerance(
    double abs_residual_tol)
{
    d_abs_residual_tol = abs_residual_tol;
    return;
}// setAbsoluteTolerance

double
LinearSolver::getAbsoluteTolerance() const
{
    return d_abs_residual_tol;
}// getAbsoluteTolerance

void
LinearSolver::setRelativeTolerance(
    double rel_residual_tol)
{
    d_rel_residual_tol = rel_residual_tol;
    return;
}// setRelativeTolerance

double
LinearSolver::getRelativeTolerance() const
{
    return d_rel_residual_tol;
}// getRelativeTolerance

int
LinearSolver::getNumIterations() const
{
    return d_current_iterations;
}// getNumIterations

double
LinearSolver::getResidualNorm() const
{
    return d_current_residual_norm;
}// getResidualNorm

void
LinearSolver::printClassData(
    std::ostream& stream)
{
    GeneralSolver::printClassData(stream);
    stream << "initial_guess_nonzero = " << d_initial_guess_nonzero << "\n"
           << "rel_residual_tol = " << d_rel_residual_tol << "\n"
           << "abs_residual_tol = " << d_abs_residual_tol << "\n"
           << "max_iterations = " << d_max_iterations << "\n"
           << "current_iterations = " << d_current_iterations << "\n"
           << "current_residual_norm = " << d_current_residual_norm << "\n"
           << "nullspace_contains_constant_vec = " << d_nullspace_contains_constant_vec << "\n"
           << "nullspace_basis_vecs.size() = " << d_nullspace_basis_vecs.size() << "\n";
    return;
}// printClassData

/////////////////////////////// PRIVATE //////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////

}// namespace IBTK

//////////////////////////////////////////////////////////////////////////////
<commit_msg>branch boyceg: fixed initialization order in LinearSolver.C<commit_after>// Filename: LinearSolver.C
// Created on 09 Sep 2003 by Boyce Griffith
//
// Copyright (c) 2002-2010, Boyce Griffith
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
//    * Redistributions of source code must retain the above copyright notice,
//      this list of conditions and the following disclaimer.
//
//    * Redistributions in binary form must reproduce the above copyright
//      notice, this list of conditions and the following disclaimer in the
//      documentation and/or other materials provided with the distribution.
//
//    * Neither the name of New York University nor the names of its
//      contributors may be used to endorse or promote products derived from
//      this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 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 "LinearSolver.h"

/////////////////////////////// INCLUDES /////////////////////////////////////

#ifndef included_IBTK_config
#include <IBTK_config.h>
#define included_IBTK_config
#endif

#ifndef included_SAMRAI_config
#include <SAMRAI_config.h>
#define included_SAMRAI_config
#endif

// IBTK INCLUDES
#include <ibtk/namespaces.h>

/////////////////////////////// NAMESPACE ////////////////////////////////////

namespace IBTK
{
/////////////////////////////// STATIC ///////////////////////////////////////

/////////////////////////////// PUBLIC ///////////////////////////////////////

LinearSolver::LinearSolver(
    const std::string& object_name,
    bool homogeneous_bc)
    : GeneralSolver(object_name, homogeneous_bc),
      d_initial_guess_nonzero(true),
      d_rel_residual_tol(1.0e-5),
      d_abs_residual_tol(1.0e-50),
      d_max_iterations(10000),
      d_current_iterations(0),
      d_current_residual_norm(std::numeric_limits<double>::quiet_NaN()),
      d_nullspace_contains_constant_vec(false),
      d_nullspace_basis_vecs()
{
    // intentionally blank
    return;
}// LinearSolver()

LinearSolver::~LinearSolver()
{
    // intentionally blank
    return;
}// ~LinearSolver()

void
LinearSolver::setNullspace(
    const bool nullspace_containsconstant_vec,
    const std::vector<Pointer<SAMRAIVectorReal<NDIM,double> > >& nullspace_basis_vecs)
{
    d_nullspace_contains_constant_vec = nullspace_containsconstant_vec;
    d_nullspace_basis_vecs = nullspace_basis_vecs;
    return;
}// setNullspace

void
LinearSolver::setInitialGuessNonzero(
    bool initial_guess_nonzero)
{
    d_initial_guess_nonzero = initial_guess_nonzero;
    return;
}// setInitialGuessNonzero

bool
LinearSolver::getNullspaceContainsConstantVector() const
{
    return d_nullspace_contains_constant_vec;
}// getNullspaceContainsConstantVector

const std::vector<Pointer<SAMRAIVectorReal<NDIM,double> > >&
LinearSolver::getNullspaceBasisVectors() const
{
    return d_nullspace_basis_vecs;
}// getNullspaceBasisVectors

bool
LinearSolver::getInitialGuessNonzero() const
{
    return d_initial_guess_nonzero;
}// getInitialGuessNonzero

void
LinearSolver::setMaxIterations(
    int max_iterations)
{
    d_max_iterations = max_iterations;
    return;
}// setMaxIterations

int
LinearSolver::getMaxIterations() const
{
    return d_max_iterations;
}// getMaxIterations

void
LinearSolver::setAbsoluteTolerance(
    double abs_residual_tol)
{
    d_abs_residual_tol = abs_residual_tol;
    return;
}// setAbsoluteTolerance

double
LinearSolver::getAbsoluteTolerance() const
{
    return d_abs_residual_tol;
}// getAbsoluteTolerance

void
LinearSolver::setRelativeTolerance(
    double rel_residual_tol)
{
    d_rel_residual_tol = rel_residual_tol;
    return;
}// setRelativeTolerance

double
LinearSolver::getRelativeTolerance() const
{
    return d_rel_residual_tol;
}// getRelativeTolerance

int
LinearSolver::getNumIterations() const
{
    return d_current_iterations;
}// getNumIterations

double
LinearSolver::getResidualNorm() const
{
    return d_current_residual_norm;
}// getResidualNorm

void
LinearSolver::printClassData(
    std::ostream& stream)
{
    GeneralSolver::printClassData(stream);
    stream << "initial_guess_nonzero = " << d_initial_guess_nonzero << "\n"
           << "rel_residual_tol = " << d_rel_residual_tol << "\n"
           << "abs_residual_tol = " << d_abs_residual_tol << "\n"
           << "max_iterations = " << d_max_iterations << "\n"
           << "current_iterations = " << d_current_iterations << "\n"
           << "current_residual_norm = " << d_current_residual_norm << "\n"
           << "nullspace_contains_constant_vec = " << d_nullspace_contains_constant_vec << "\n"
           << "nullspace_basis_vecs.size() = " << d_nullspace_basis_vecs.size() << "\n";
    return;
}// printClassData

/////////////////////////////// PRIVATE //////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////

}// namespace IBTK

//////////////////////////////////////////////////////////////////////////////
<|endoftext|>


<commit_before>#include <stdio.h>
#include <algorithm>
#include "GIF.h"
#include "uint128.h"
#include "Ps2Const.h"
#include "Profiler.h"
#include "Log.h"

using namespace Framework;
using namespace std;
using namespace boost;

#ifdef	PROFILE
#define PROFILE_GIFZONE		"GIF"
#endif

CGIF::CGIF(CGSHandler*& gs, uint8* ram, uint8* spr) :
m_gs(gs),
m_ram(ram),
m_spr(spr),
m_nLoops(0),
m_nCmd(0),
m_nRegs(0),
m_nRegsTemp(0),
m_nRegList(0),
m_nEOP(false),
m_nQTemp(0)
{

}

CGIF::~CGIF()
{

}

void CGIF::Reset()
{
	m_nLoops = 0;
	m_nCmd = 0;
	m_nEOP = false;
}

uint32 CGIF::ProcessPacked(CGSHandler::RegisterWriteList& writeList, uint8* pMemory, uint32 nAddress, uint32 nEnd)
{
	uint32 nRegDesc, nStart;
	uint64 nTemp;
	uint128 nPacket;

	nStart = nAddress;

	while((m_nLoops != 0) && (nAddress < nEnd))
	{
		while((m_nRegsTemp != 0) && (nAddress < nEnd))
		{
			nRegDesc = (uint32)((m_nRegList >> ((m_nRegs - m_nRegsTemp) * 4)) & 0x0F);

			nPacket = *(uint128*)&pMemory[nAddress];
			nAddress += 0x10;

			m_nRegsTemp--;

			switch(nRegDesc)
			{
            case 0x00:
                //PRIM
                writeList.push_back(CGSHandler::RegisterWrite(GS_REG_PRIM, nPacket.nV0));
                break;
			case 0x01:
				//RGBA
				nTemp  = (nPacket.nV[0] & 0xFF);
				nTemp |= (nPacket.nV[1] & 0xFF) << 8;
				nTemp |= (nPacket.nV[2] & 0xFF) << 16;
				nTemp |= (nPacket.nV[3] & 0xFF) << 24;
				nTemp |= ((uint64)m_nQTemp << 32);
                writeList.push_back(CGSHandler::RegisterWrite(GS_REG_RGBAQ, nTemp));
				break;
			case 0x02:
				//ST
				m_nQTemp = nPacket.nV2;
                writeList.push_back(CGSHandler::RegisterWrite(GS_REG_ST, nPacket.nD0));
				break;
			case 0x03:
				//UV
				nTemp  = (nPacket.nV[0] & 0x7FFF);
				nTemp |= (nPacket.nV[1] & 0x7FFF) << 16;
                writeList.push_back(CGSHandler::RegisterWrite(GS_REG_UV, nTemp));
				break;
			case 0x04:
				//XYZF2
				nTemp  = (nPacket.nV[0] & 0xFFFF);
				nTemp |= (nPacket.nV[1] & 0xFFFF) << 16;
				nTemp |= (uint64)(nPacket.nV[2] & 0x0FFFFFF0) << 28;
				nTemp |= (uint64)(nPacket.nV[3] & 0x00000FF0) << 52;
				if(nPacket.nV[3] & 0x8000)
				{
                    writeList.push_back(CGSHandler::RegisterWrite(GS_REG_XYZF3, nTemp));
				}
				else
				{
                    writeList.push_back(CGSHandler::RegisterWrite(GS_REG_XYZF2, nTemp));
				}
				break;
			case 0x05:
				//XYZ2
				nTemp  = (nPacket.nV[0] & 0xFFFF);
				nTemp |= (nPacket.nV[1] & 0xFFFF) << 16;
				nTemp |= (uint64)(nPacket.nV[2] & 0xFFFFFFFF) << 32;
				if(nPacket.nV[3] & 0x8000)
				{
                    writeList.push_back(CGSHandler::RegisterWrite(GS_REG_XYZ3, nTemp));
				}
				else
				{
                    writeList.push_back(CGSHandler::RegisterWrite(GS_REG_XYZ2, nTemp));
				}
				break;
			case 0x06:
				//TEX0_1
                writeList.push_back(CGSHandler::RegisterWrite(GS_REG_TEX0_1, nPacket.nD0));
				break;
            case 0x08:
                //CLAMP_1
                writeList.push_back(CGSHandler::RegisterWrite(GS_REG_CLAMP_1, nPacket.nD0));
                break;
			case 0x0E:
				//A + D
				if(m_gs != NULL)
				{
                    writeList.push_back(CGSHandler::RegisterWrite(static_cast<uint8>(nPacket.nD1), nPacket.nD0));
				}
				break;
            case 0x0F:
                //NOP
                break;
			default:
				assert(0);
				break;
			}
		}

		if(m_nRegsTemp == 0)
		{
			m_nLoops--;
			m_nRegsTemp = m_nRegs;
		}

	}

	return nAddress - nStart;
}

uint32 CGIF::ProcessRegList(CGSHandler::RegisterWriteList& writeList, uint8* pMemory, uint32 nAddress, uint32 nEnd)
{
    uint32 nStart = nAddress;

	while(m_nLoops != 0)
	{
		for(uint32 j = 0; j < m_nRegs; j++)
		{
			assert(nAddress < nEnd);

	        uint128 nPacket;
			uint32 nRegDesc = (uint32)((m_nRegList >> (j * 4)) & 0x0F);

 			nPacket.nV[0] = *(uint32*)&pMemory[nAddress + 0x00];
			nPacket.nV[1] = *(uint32*)&pMemory[nAddress + 0x04];
			nAddress += 0x08;

			if(nRegDesc == 0x0F) continue;

            writeList.push_back(CGSHandler::RegisterWrite(static_cast<uint8>(nRegDesc), nPacket.nD0));
		}

		m_nLoops--;
	}

	//Align on qword boundary
	if(nAddress & 0x07)
	{
		nAddress += 8;
	}

	return nAddress - nStart;
}

uint32 CGIF::ProcessImage(uint8* pMemory, uint32 nAddress, uint32 nEnd)
{
	uint16 nTotalLoops;

	nTotalLoops = (uint16)((nEnd - nAddress) / 0x10);
	nTotalLoops = min(nTotalLoops, m_nLoops);

	if(m_gs != NULL)
	{
		m_gs->FeedImageData(pMemory + nAddress, nTotalLoops * 0x10);
	}

	m_nLoops -= nTotalLoops;

	return (nTotalLoops * 0x10);
}

uint32 CGIF::ProcessPacket(uint8* pMemory, uint32 nAddress, uint32 nEnd)
{
    mutex::scoped_lock pathLock(m_pathMutex);
    static CGSHandler::RegisterWriteList writeList;

#ifdef PROFILE
	CProfiler::GetInstance().BeginZone(PROFILE_GIFZONE);
#endif

#ifdef _DEBUG
    CLog::GetInstance().Print("gif", "Processed GIF packet at 0x%0.8X.\r\n", nAddress);
#endif

    writeList.clear();

    uint32 nStart = nAddress;
	while(nAddress < nEnd)
	{
		if(m_nLoops == 0)
		{
			if(m_nEOP)
			{
				m_nEOP = false;
				break;
			}

			//We need to update the registers
			uint128 nPacket = *reinterpret_cast<uint128*>(&pMemory[nAddress]);
			nAddress += 0x10;

			m_nLoops	= (uint16)((nPacket.nV0 >>  0) & 0x7FFF);
			m_nCmd		= ( uint8)((nPacket.nV1 >> 26) & 0x0003);
			m_nRegs		= ( uint8)((nPacket.nV1 >> 28) & 0x000F);
			m_nRegList	= nPacket.nD1;
			m_nEOP		= (nPacket.nV0 & 0x8000) != 0;

			if(m_nCmd != 1)
			{
				if(nPacket.nV1 & 0x4000)
				{
                    writeList.push_back(CGSHandler::RegisterWrite(GS_REG_PRIM, (uint16)(nPacket.nV1 >> 15) & 0x3FF));
				}
			}

			if(m_nRegs == 0) m_nRegs = 0x10;
			m_nRegsTemp = m_nRegs;
			continue;
		}
		switch(m_nCmd)
		{
		case 0x00:
			nAddress += ProcessPacked(writeList, pMemory, nAddress, nEnd);
			break;
		case 0x01:
			nAddress += ProcessRegList(writeList, pMemory, nAddress, nEnd);
			break;
		case 0x02:
		case 0x03:
			nAddress += ProcessImage(pMemory, nAddress, nEnd);
			break;
		}
	}

	if(m_nLoops == 0)
	{
		if(m_nEOP)
		{
			m_nEOP = false;
		}
	}

#ifdef PROFILE
	CProfiler::GetInstance().EndZone();
#endif

    if(m_gs != NULL && writeList.size() != 0)
    {
        CGSHandler::RegisterWrite* writeListBuffer = new CGSHandler::RegisterWrite[writeList.size()];
        memcpy(writeListBuffer, &writeList[0], sizeof(CGSHandler::RegisterWrite) * writeList.size());
        m_gs->WriteRegisterMassively(writeListBuffer, static_cast<unsigned int>(writeList.size()));
    }

    return nAddress - nStart;
}

uint32 CGIF::ReceiveDMA(uint32 nAddress, uint32 nQWC, uint32 unused, bool nTagIncluded)
{
	uint8* pMemory;

    assert(nTagIncluded == false);

	if(nAddress & 0x80000000)
	{
		pMemory = m_spr;
		nAddress &= PS2::SPRSIZE - 1;
	}
	else
	{
		pMemory = m_ram;
	}

	uint32 nSize = nQWC * 0x10;
	uint32 nEnd = nAddress + nSize;

	while(nAddress < nEnd)
	{
		nAddress += ProcessPacket(pMemory, nAddress, nEnd);
	}

	return nQWC;
}
<commit_msg>Added DMAtag skipping in GIF.<commit_after>#include <stdio.h>
#include <algorithm>
#include "GIF.h"
#include "uint128.h"
#include "Ps2Const.h"
#include "Profiler.h"
#include "Log.h"

using namespace Framework;
using namespace std;
using namespace boost;

#ifdef	PROFILE
#define PROFILE_GIFZONE		"GIF"
#endif

CGIF::CGIF(CGSHandler*& gs, uint8* ram, uint8* spr) :
m_gs(gs),
m_ram(ram),
m_spr(spr),
m_nLoops(0),
m_nCmd(0),
m_nRegs(0),
m_nRegsTemp(0),
m_nRegList(0),
m_nEOP(false),
m_nQTemp(0)
{

}

CGIF::~CGIF()
{

}

void CGIF::Reset()
{
	m_nLoops = 0;
	m_nCmd = 0;
	m_nEOP = false;
}

uint32 CGIF::ProcessPacked(CGSHandler::RegisterWriteList& writeList, uint8* pMemory, uint32 nAddress, uint32 nEnd)
{
	uint32 nRegDesc, nStart;
	uint64 nTemp;
	uint128 nPacket;

	nStart = nAddress;

	while((m_nLoops != 0) && (nAddress < nEnd))
	{
		while((m_nRegsTemp != 0) && (nAddress < nEnd))
		{
			nRegDesc = (uint32)((m_nRegList >> ((m_nRegs - m_nRegsTemp) * 4)) & 0x0F);

			nPacket = *(uint128*)&pMemory[nAddress];
			nAddress += 0x10;

			m_nRegsTemp--;

			switch(nRegDesc)
			{
            case 0x00:
                //PRIM
                writeList.push_back(CGSHandler::RegisterWrite(GS_REG_PRIM, nPacket.nV0));
                break;
			case 0x01:
				//RGBA
				nTemp  = (nPacket.nV[0] & 0xFF);
				nTemp |= (nPacket.nV[1] & 0xFF) << 8;
				nTemp |= (nPacket.nV[2] & 0xFF) << 16;
				nTemp |= (nPacket.nV[3] & 0xFF) << 24;
				nTemp |= ((uint64)m_nQTemp << 32);
                writeList.push_back(CGSHandler::RegisterWrite(GS_REG_RGBAQ, nTemp));
				break;
			case 0x02:
				//ST
				m_nQTemp = nPacket.nV2;
                writeList.push_back(CGSHandler::RegisterWrite(GS_REG_ST, nPacket.nD0));
				break;
			case 0x03:
				//UV
				nTemp  = (nPacket.nV[0] & 0x7FFF);
				nTemp |= (nPacket.nV[1] & 0x7FFF) << 16;
                writeList.push_back(CGSHandler::RegisterWrite(GS_REG_UV, nTemp));
				break;
			case 0x04:
				//XYZF2
				nTemp  = (nPacket.nV[0] & 0xFFFF);
				nTemp |= (nPacket.nV[1] & 0xFFFF) << 16;
				nTemp |= (uint64)(nPacket.nV[2] & 0x0FFFFFF0) << 28;
				nTemp |= (uint64)(nPacket.nV[3] & 0x00000FF0) << 52;
				if(nPacket.nV[3] & 0x8000)
				{
                    writeList.push_back(CGSHandler::RegisterWrite(GS_REG_XYZF3, nTemp));
				}
				else
				{
                    writeList.push_back(CGSHandler::RegisterWrite(GS_REG_XYZF2, nTemp));
				}
				break;
			case 0x05:
				//XYZ2
				nTemp  = (nPacket.nV[0] & 0xFFFF);
				nTemp |= (nPacket.nV[1] & 0xFFFF) << 16;
				nTemp |= (uint64)(nPacket.nV[2] & 0xFFFFFFFF) << 32;
				if(nPacket.nV[3] & 0x8000)
				{
                    writeList.push_back(CGSHandler::RegisterWrite(GS_REG_XYZ3, nTemp));
				}
				else
				{
                    writeList.push_back(CGSHandler::RegisterWrite(GS_REG_XYZ2, nTemp));
				}
				break;
			case 0x06:
				//TEX0_1
                writeList.push_back(CGSHandler::RegisterWrite(GS_REG_TEX0_1, nPacket.nD0));
				break;
            case 0x08:
                //CLAMP_1
                writeList.push_back(CGSHandler::RegisterWrite(GS_REG_CLAMP_1, nPacket.nD0));
                break;
			case 0x0E:
				//A + D
				if(m_gs != NULL)
				{
                    writeList.push_back(CGSHandler::RegisterWrite(static_cast<uint8>(nPacket.nD1), nPacket.nD0));
				}
				break;
            case 0x0F:
                //NOP
                break;
			default:
				assert(0);
				break;
			}
		}

		if(m_nRegsTemp == 0)
		{
			m_nLoops--;
			m_nRegsTemp = m_nRegs;
		}

	}

	return nAddress - nStart;
}

uint32 CGIF::ProcessRegList(CGSHandler::RegisterWriteList& writeList, uint8* pMemory, uint32 nAddress, uint32 nEnd)
{
    uint32 nStart = nAddress;

	while(m_nLoops != 0)
	{
		for(uint32 j = 0; j < m_nRegs; j++)
		{
			assert(nAddress < nEnd);

	        uint128 nPacket;
			uint32 nRegDesc = (uint32)((m_nRegList >> (j * 4)) & 0x0F);

 			nPacket.nV[0] = *(uint32*)&pMemory[nAddress + 0x00];
			nPacket.nV[1] = *(uint32*)&pMemory[nAddress + 0x04];
			nAddress += 0x08;

			if(nRegDesc == 0x0F) continue;

            writeList.push_back(CGSHandler::RegisterWrite(static_cast<uint8>(nRegDesc), nPacket.nD0));
		}

		m_nLoops--;
	}

	//Align on qword boundary
	if(nAddress & 0x07)
	{
		nAddress += 8;
	}

	return nAddress - nStart;
}

uint32 CGIF::ProcessImage(uint8* pMemory, uint32 nAddress, uint32 nEnd)
{
	uint16 nTotalLoops;

	nTotalLoops = (uint16)((nEnd - nAddress) / 0x10);
	nTotalLoops = min(nTotalLoops, m_nLoops);

	if(m_gs != NULL)
	{
		m_gs->FeedImageData(pMemory + nAddress, nTotalLoops * 0x10);
	}

	m_nLoops -= nTotalLoops;

	return (nTotalLoops * 0x10);
}

uint32 CGIF::ProcessPacket(uint8* pMemory, uint32 nAddress, uint32 nEnd)
{
    mutex::scoped_lock pathLock(m_pathMutex);
    static CGSHandler::RegisterWriteList writeList;

#ifdef PROFILE
	CProfiler::GetInstance().BeginZone(PROFILE_GIFZONE);
#endif

#ifdef _DEBUG
    CLog::GetInstance().Print("gif", "Processed GIF packet at 0x%0.8X.\r\n", nAddress);
#endif

    writeList.clear();

    uint32 nStart = nAddress;
	while(nAddress < nEnd)
	{
		if(m_nLoops == 0)
		{
			if(m_nEOP)
			{
				m_nEOP = false;
				break;
			}

			//We need to update the registers
			uint128 nPacket = *reinterpret_cast<uint128*>(&pMemory[nAddress]);
			nAddress += 0x10;

			m_nLoops	= (uint16)((nPacket.nV0 >>  0) & 0x7FFF);
			m_nCmd		= ( uint8)((nPacket.nV1 >> 26) & 0x0003);
			m_nRegs		= ( uint8)((nPacket.nV1 >> 28) & 0x000F);
			m_nRegList	= nPacket.nD1;
			m_nEOP		= (nPacket.nV0 & 0x8000) != 0;

			if(m_nCmd != 1)
			{
				if(nPacket.nV1 & 0x4000)
				{
                    writeList.push_back(CGSHandler::RegisterWrite(GS_REG_PRIM, (uint16)(nPacket.nV1 >> 15) & 0x3FF));
				}
			}

			if(m_nRegs == 0) m_nRegs = 0x10;
			m_nRegsTemp = m_nRegs;
			continue;
		}
		switch(m_nCmd)
		{
		case 0x00:
			nAddress += ProcessPacked(writeList, pMemory, nAddress, nEnd);
			break;
		case 0x01:
			nAddress += ProcessRegList(writeList, pMemory, nAddress, nEnd);
			break;
		case 0x02:
		case 0x03:
			nAddress += ProcessImage(pMemory, nAddress, nEnd);
			break;
		}
	}

	if(m_nLoops == 0)
	{
		if(m_nEOP)
		{
			m_nEOP = false;
		}
	}

#ifdef PROFILE
	CProfiler::GetInstance().EndZone();
#endif

    if(m_gs != NULL && writeList.size() != 0)
    {
        CGSHandler::RegisterWrite* writeListBuffer = new CGSHandler::RegisterWrite[writeList.size()];
        memcpy(writeListBuffer, &writeList[0], sizeof(CGSHandler::RegisterWrite) * writeList.size());
        m_gs->WriteRegisterMassively(writeListBuffer, static_cast<unsigned int>(writeList.size()));
    }

    return nAddress - nStart;
}

uint32 CGIF::ReceiveDMA(uint32 nAddress, uint32 nQWC, uint32 unused, bool nTagIncluded)
{
	uint8* pMemory(NULL);
	uint32 nSize = nQWC * 0x10;

    if(nTagIncluded)
    {
        assert(nQWC >= 0);
        nSize -= 0x10;
        nAddress += 0x10;
    }

	if(nAddress & 0x80000000)
	{
		pMemory = m_spr;
		nAddress &= PS2::SPRSIZE - 1;
	}
	else
	{
		pMemory = m_ram;
	}

	uint32 nEnd = nAddress + nSize;

	while(nAddress < nEnd)
	{
		nAddress += ProcessPacket(pMemory, nAddress, nEnd);
	}

	return nQWC;
}
<|endoftext|>


<commit_before>#ifndef CMDSTAN_ARGUMENTS_ARG_OUTPUT_SIG_FIGS_HPP
#define CMDSTAN_ARGUMENTS_ARG_OUTPUT_SIG_FIGS_HPP

#include <cmdstan/arguments/singleton_argument.hpp>

namespace cmdstan {

class arg_output_sig_figs : public int_argument {
 public:
  arg_output_sig_figs() : int_argument() {
    _name = "sig_figs";
    _description = "The number of significant figures used for the output CSV files.";
    _validity = "0 <= integer <= 18 or -1 to use the default number of significant figures";
    _default = "-1";
    _default_value = -1;
    _constrained = true;
    _good_value = 8;
    _bad_value = -2;
    _value = _default_value;
  }

  bool is_valid(int value) { return value >= 0 || value == _default_value; }
};

}  // namespace cmdstan
#endif
<commit_msg>[Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.04.1 (tags/RELEASE_600/final)<commit_after>#ifndef CMDSTAN_ARGUMENTS_ARG_OUTPUT_SIG_FIGS_HPP
#define CMDSTAN_ARGUMENTS_ARG_OUTPUT_SIG_FIGS_HPP

#include <cmdstan/arguments/singleton_argument.hpp>

namespace cmdstan {

class arg_output_sig_figs : public int_argument {
 public:
  arg_output_sig_figs() : int_argument() {
    _name = "sig_figs";
    _description
        = "The number of significant figures used for the output CSV files.";
    _validity
        = "0 <= integer <= 18 or -1 to use the default number of significant "
          "figures";
    _default = "-1";
    _default_value = -1;
    _constrained = true;
    _good_value = 8;
    _bad_value = -2;
    _value = _default_value;
  }

  bool is_valid(int value) { return value >= 0 || value == _default_value; }
};

}  // namespace cmdstan
#endif
<|endoftext|>


<commit_before>/* ========== HTTP://WWW.SOURCEFORGE.NET/PROJECTS/CRYSTAL ==========
 *
 * FILE: gl_vbufext.cpp
 *
 * DESCRIPTION:
 *  Implements a Vertex Buffer suitable for forming triangle strips, as well
 *  as individual triangles.
 *
 * LICENSE:
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Library General Public
 *  License as published by the Free Software Foundation; either
 *  version 2 of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Library General Public License for more details.
 *
 *  You should have received a copy of the GNU Library General Public
 *  License along with this library; if not, write to the Free
 *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 *
 * AUTHOR:
 *    Thomas H. Hendrick
 *
 * CVS/RCS ID:
 *    $Id$
 *
 * === COPYRIGHT (c)2002 ============== PROJECT CRYSTAL SPACE 3D === */
/* -----------------------------------------------------------------
 * Preprocessor Includes
 * ----------------------------------------------------------------- */

#include <math.h>
#include <stdarg.h>

#include "cssysdef.h"
#include "gl_polybufext.h"
#include "csutil/util.h"
#include "imesh/thing/polygon.h"
#include "qint.h"

csPolygonBufferEXT::csPolygonBufferEXT(iGraphics3D *g3d)
{
}

csPolygonBufferEXT::~csPolygonBufferEXT()
{
}

void csPolygonBufferEXT::AddPolygon (int* verts, int num_verts,
	const csPlane3& poly_normal,
	int mat_index,
	const csMatrix3& m_obj2tex, const csVector3& v_obj2tex,
	iPolygonTexture* poly_texture)
{
}

void csPolygonBufferEXT::SetVertexArray (csVector3* verts, int num_verts)
{
}

void csPolygonBufferEXT::AddMaterial (iMaterialHandle* mat_handle)
{
}

int csPolygonBufferEXT::GetMaterialCount () const
{
 return 0;
}

iMaterialHandle* csPolygonBufferEXT::GetMaterial (int idx) const
{
}

int csPolygonBufferEXT::GetVertexCount() const
{
}

csVector3* csPolygonBufferEXT::GetVertices() const
{
}

void csPolygonBufferEXT::SetMaterial (int idx, iMaterialHandle* mat_handle)
{
}

void csPolygonBufferEXT::Clear ()
{
}

void csPolygonBufferEXT::MarkLightmapsDirty()
{
}<commit_msg>Added some spurious returns to fix compile errors under MSVC. These should just be removed when real code is inserted.<commit_after>/* ========== HTTP://WWW.SOURCEFORGE.NET/PROJECTS/CRYSTAL ==========
 *
 * FILE: gl_vbufext.cpp
 *
 * DESCRIPTION:
 *  Implements a Vertex Buffer suitable for forming triangle strips, as well
 *  as individual triangles.
 *
 * LICENSE:
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Library General Public
 *  License as published by the Free Software Foundation; either
 *  version 2 of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Library General Public License for more details.
 *
 *  You should have received a copy of the GNU Library General Public
 *  License along with this library; if not, write to the Free
 *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 *
 * AUTHOR:
 *    Thomas H. Hendrick
 *
 * CVS/RCS ID:
 *    $Id$
 *
 * === COPYRIGHT (c)2002 ============== PROJECT CRYSTAL SPACE 3D === */
/* -----------------------------------------------------------------
 * Preprocessor Includes
 * ----------------------------------------------------------------- */

#include <math.h>
#include <stdarg.h>

#include "cssysdef.h"
#include "gl_polybufext.h"
#include "csutil/util.h"
#include "imesh/thing/polygon.h"
#include "qint.h"

csPolygonBufferEXT::csPolygonBufferEXT(iGraphics3D *g3d)
{
}

csPolygonBufferEXT::~csPolygonBufferEXT()
{
}

void csPolygonBufferEXT::AddPolygon (int* verts, int num_verts,
	const csPlane3& poly_normal,
	int mat_index,
	const csMatrix3& m_obj2tex, const csVector3& v_obj2tex,
	iPolygonTexture* poly_texture)
{
}

void csPolygonBufferEXT::SetVertexArray (csVector3* verts, int num_verts)
{
}

void csPolygonBufferEXT::AddMaterial (iMaterialHandle* mat_handle)
{
}

int csPolygonBufferEXT::GetMaterialCount () const
{
  return 0;
}

iMaterialHandle* csPolygonBufferEXT::GetMaterial (int idx) const
{
  return NULL; // Done only to fix compile errors. Change when necesary.
}

int csPolygonBufferEXT::GetVertexCount() const
{
  return 0; // Done only to fix compile errors. Change when necesary.
}

csVector3* csPolygonBufferEXT::GetVertices() const
{
  return NULL;// Done only to fix compile errors. Change when necesary.
}

void csPolygonBufferEXT::SetMaterial (int idx, iMaterialHandle* mat_handle)
{
}

void csPolygonBufferEXT::Clear ()
{
}

void csPolygonBufferEXT::MarkLightmapsDirty()
{
}<|endoftext|>


<commit_before>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2016.  All rights reserved
 */
#ifndef _Stroika_Foundation_Characters_ToString_inl_
#define _Stroika_Foundation_Characters_ToString_inl_    1

#include    <wchar.h>
#include    <exception>
#include    "../Configuration/Concepts.h"
#include    "../Configuration/Enumeration.h"
#include    "FloatConversion.h"
#include    "StringBuilder.h"
#include    "String_Constant.h"

/*
 ********************************************************************************
 ***************************** Implementation Details ***************************
 ********************************************************************************
 */
namespace   Stroika {
    namespace   Foundation {
        namespace   Characters {

            /*
             ********************************************************************************
             ********************************* ToString *************************************
             ********************************************************************************
             */
            namespace Private_ {

                STROIKA_FOUNDATION_CONFIGURATION_DEFINE_HAS(ToString, (x.ToString ()));
                STROIKA_FOUNDATION_CONFIGURATION_DEFINE_HAS(beginenditerable, (x.begin () != x.end ()));
                STROIKA_FOUNDATION_CONFIGURATION_DEFINE_HAS(pair, (x.first, x.second));
                STROIKA_FOUNDATION_CONFIGURATION_DEFINE_HAS(KeyValuePair, (x.fKey, x.fValue));
                STROIKA_FOUNDATION_CONFIGURATION_DEFINE_HAS(CountedValue, (x.fValue, x.fCount));

                String  ToString_exception_ptr (const exception_ptr& e);

                template    <typename T>
                inline  String  ToString_ (const T& t, typename enable_if<has_ToString<T>::value>::type* = 0)
                {
                    return t.ToString ();
                }

                template    <typename T>
                inline  String  ToString_ (const T& t, typename enable_if<is_same<T, exception_ptr>::value>::type* = 0)
                {
                    return ToString_exception_ptr (t);
                }

                template    <typename T>
                inline  String  ToString_ (const T& t, typename enable_if<has_beginenditerable<T>::value and not has_ToString<T>::value and not is_convertible<T, String>::value>::type* = 0)
                {
                    StringBuilder sb;
                    sb << L"{";
                    bool didFirst { false };
                    for (auto i : t) {
                        if (didFirst) {
                            sb << L", ";
                        }
                        else {
                            sb << L" ";
                        }
                        sb << ToString (i);
                        didFirst = true;
                    }
                    if (didFirst) {
                        sb << L" ";
                    }
                    sb << L"}";
                    return sb.str ();
                }

                template    <typename T>
                inline  String  ToString_ (const T& t, typename enable_if<is_convertible<T, String>::value>::type* = 0)
                {
                    return static_cast<String> (t);
                }

                template    <typename T>
                inline  String  ToString_ (const T& t, typename enable_if<has_pair<T>::value>::type* = 0)
                {
                    StringBuilder sb;
                    sb << L"{";
                    sb << L"'" << ToString (t.first) << L"': " << ToString (t.second);
                    sb << L"}";
                    return sb.str ();
                }

                template    <typename T>
                inline  String  ToString_ (const T& t, typename enable_if<has_KeyValuePair<T>::value>::type* = 0)
                {
                    StringBuilder sb;
                    sb << L"{";
                    sb << L"'" << ToString (t.fKey) << L"': " << ToString (t.fValue);
                    sb << L"}";
                    return sb.str ();
                }

                template    <typename T>
                inline  String  ToString_ (const T& t, typename enable_if<has_CountedValue<T>::value>::type* = 0)
                {
                    StringBuilder sb;
                    sb << L"{";
                    sb << L"'" << ToString (t.fValue) << L"': " << ToString (t.fCount);
                    sb << L"}";
                    return sb.str ();
                }

                template    <typename T>
                inline  String  ToString_ (const T& t, typename enable_if<is_enum<T>::value>::type* = 0)
                {
                    // SHOULD MAYBE only do if can detect is-defined Configuration::DefaultNames<T>, but right now not easy, and
                    // not a problem: just dont call this, or replace it with a specific specialization of ToString
                    return Configuration::DefaultNames<T>::k.GetName (t);
                }

                /*
                 * From section from section 3.9.1 of http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3337.pdf
                 *      There are five standard signed integer types : signed char, short int, int,
                 *      long int, and long long int. In this list, each type provides at least as much
                 *      storage as those preceding it in the list.
                 *      For each of the standard signed integer types, there exists a corresponding (but different)
                 *      standard unsigned integer type: unsigned char, unsigned short int, unsigned int, unsigned long int,
                 *      and unsigned long long int, each of which occupies the same amount of storage and has the
                 *      same alignment requirements.
                 */
                template    <typename T>
                inline  String  ToString_ (const T& t, typename enable_if<is_same<T, bool>::value>::type* = 0)
                {
                    return t ? String_Constant { L"true" } :
                           String_Constant { L"false" };
                }
                template    <typename T>
                inline  String  ToString_ (const T& t, typename enable_if<is_same<T, signed char>::value>::type* = 0)
                {
                    wchar_t buf[1024];
                    (void)::swprintf (buf, NEltsOf (buf), L"%d", t);
                    return buf;
                }
                template    <typename T>
                inline  String  ToString_ (const T& t, typename enable_if<is_same<T, short int>::value>::type* = 0)
                {
                    wchar_t buf[1024];
                    (void)::swprintf (buf, NEltsOf (buf), L"%d", t);
                    return buf;
                }
                template    <typename T>
                inline  String  ToString_ (const T& t, typename enable_if<is_same<T, int>::value>::type* = 0)
                {
                    wchar_t buf[1024];
                    (void)::swprintf (buf, NEltsOf (buf), L"%d", t);
                    return buf;
                }
                template    <typename T>
                inline  String  ToString_ (const T& t, typename enable_if<is_same<T, long int>::value>::type* = 0)
                {
                    wchar_t buf[1024];
                    (void)::swprintf (buf, NEltsOf (buf), L"%ld", t);
                    return buf;
                }
                template    <typename T>
                inline  String  ToString_ (const T& t, typename enable_if<is_same<T, long long int>::value>::type* = 0)
                {
                    wchar_t buf[1024];
                    (void)::swprintf (buf, NEltsOf (buf), L"%lld", t);
                    return buf;
                }
                template    <typename T>
                inline  String  ToString_ (const T& t, typename enable_if<is_same<T, unsigned char>::value>::type* = 0)
                {
                    wchar_t buf[1024];
                    (void)::swprintf (buf, NEltsOf (buf), L"0x%x", t);
                    return buf;
                }
                template    <typename T>
                inline  String  ToString_ (const T& t, typename enable_if<is_same<T, unsigned short>::value>::type* = 0)
                {
                    wchar_t buf[1024];
                    (void)::swprintf (buf, NEltsOf (buf), L"0x%x", t);
                    return buf;
                }
                template    <typename T>
                inline  String  ToString_ (const T& t, typename enable_if<is_same<T, unsigned int>::value>::type* = 0)
                {
                    wchar_t buf[1024];
                    (void)::swprintf (buf, NEltsOf (buf), L"0x%x", t);
                    return buf;
                }
                template    <typename T>
                inline  String  ToString_ (const T& t, typename enable_if<is_same<T, unsigned long>::value>::type* = 0)
                {
                    wchar_t buf[1024];
                    (void)::swprintf (buf, NEltsOf (buf), L"0x%lx", t);
                    return buf;
                }
                template    <typename T>
                inline  String  ToString_ (const T& t, typename enable_if<is_same<T, unsigned long long>::value>::type* = 0)
                {
                    wchar_t buf[1024];
                    (void)::swprintf (buf, NEltsOf (buf), L"0x%llx", t);
                    return buf;
                }

                template    <typename T>
                inline  String  ToString_ (const T& t, typename enable_if < is_floating_point<T>::value>::type* = 0)
                {
                    return Float2String (t);
                }
            }

            template    <typename T>
            inline  String  ToString (const T& t)
            {
                return Private_::ToString_<T> (t);
            }

        }
    }
}
#endif  /*_Stroika_Foundation_Characters_ToString_inl_*/
<commit_msg>slightly less aggressive inlining in ToString impls<commit_after>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2016.  All rights reserved
 */
#ifndef _Stroika_Foundation_Characters_ToString_inl_
#define _Stroika_Foundation_Characters_ToString_inl_    1

#include    <wchar.h>
#include    <exception>
#include    "../Configuration/Concepts.h"
#include    "../Configuration/Enumeration.h"
#include    "FloatConversion.h"
#include    "StringBuilder.h"
#include    "String_Constant.h"

/*
 ********************************************************************************
 ***************************** Implementation Details ***************************
 ********************************************************************************
 */
namespace   Stroika {
    namespace   Foundation {
        namespace   Characters {

            /*
             ********************************************************************************
             ********************************* ToString *************************************
             ********************************************************************************
             */
            namespace Private_ {

                STROIKA_FOUNDATION_CONFIGURATION_DEFINE_HAS(ToString, (x.ToString ()));
                STROIKA_FOUNDATION_CONFIGURATION_DEFINE_HAS(beginenditerable, (x.begin () != x.end ()));
                STROIKA_FOUNDATION_CONFIGURATION_DEFINE_HAS(pair, (x.first, x.second));
                STROIKA_FOUNDATION_CONFIGURATION_DEFINE_HAS(KeyValuePair, (x.fKey, x.fValue));
                STROIKA_FOUNDATION_CONFIGURATION_DEFINE_HAS(CountedValue, (x.fValue, x.fCount));

                String  ToString_exception_ptr (const exception_ptr& e);

                template    <typename T>
                inline  String  ToString_ (const T& t, typename enable_if<has_ToString<T>::value>::type* = 0)
                {
                    return t.ToString ();
                }

                template    <typename T>
                inline  String  ToString_ (const T& t, typename enable_if<is_same<T, exception_ptr>::value>::type* = 0)
                {
                    return ToString_exception_ptr (t);
                }

                template    <typename T>
                String  ToString_ (const T& t, typename enable_if<has_beginenditerable<T>::value and not has_ToString<T>::value and not is_convertible<T, String>::value>::type* = 0)
                {
                    StringBuilder sb;
                    sb << L"{";
                    bool didFirst { false };
                    for (auto i : t) {
                        if (didFirst) {
                            sb << L", ";
                        }
                        else {
                            sb << L" ";
                        }
                        sb << ToString (i);
                        didFirst = true;
                    }
                    if (didFirst) {
                        sb << L" ";
                    }
                    sb << L"}";
                    return sb.str ();
                }

                template    <typename T>
                inline  String  ToString_ (const T& t, typename enable_if<is_convertible<T, String>::value>::type* = 0)
                {
                    return static_cast<String> (t);
                }

                template    <typename T>
                String  ToString_ (const T& t, typename enable_if<has_pair<T>::value>::type* = 0)
                {
                    StringBuilder sb;
                    sb << L"{";
                    sb << L"'" << ToString (t.first) << L"': " << ToString (t.second);
                    sb << L"}";
                    return sb.str ();
                }

                template    <typename T>
                String  ToString_ (const T& t, typename enable_if<has_KeyValuePair<T>::value>::type* = 0)
                {
                    StringBuilder sb;
                    sb << L"{";
                    sb << L"'" << ToString (t.fKey) << L"': " << ToString (t.fValue);
                    sb << L"}";
                    return sb.str ();
                }

                template    <typename T>
                String  ToString_ (const T& t, typename enable_if<has_CountedValue<T>::value>::type* = 0)
                {
                    StringBuilder sb;
                    sb << L"{";
                    sb << L"'" << ToString (t.fValue) << L"': " << ToString (t.fCount);
                    sb << L"}";
                    return sb.str ();
                }

                template    <typename T>
                inline  String  ToString_ (const T& t, typename enable_if<is_enum<T>::value>::type* = 0)
                {
                    // SHOULD MAYBE only do if can detect is-defined Configuration::DefaultNames<T>, but right now not easy, and
                    // not a problem: just dont call this, or replace it with a specific specialization of ToString
                    return Configuration::DefaultNames<T>::k.GetName (t);
                }

                /*
                 * From section from section 3.9.1 of http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3337.pdf
                 *      There are five standard signed integer types : signed char, short int, int,
                 *      long int, and long long int. In this list, each type provides at least as much
                 *      storage as those preceding it in the list.
                 *      For each of the standard signed integer types, there exists a corresponding (but different)
                 *      standard unsigned integer type: unsigned char, unsigned short int, unsigned int, unsigned long int,
                 *      and unsigned long long int, each of which occupies the same amount of storage and has the
                 *      same alignment requirements.
                 */
                template    <typename T>
                inline  String  ToString_ (const T& t, typename enable_if<is_same<T, bool>::value>::type* = 0)
                {
                    return t ? String_Constant { L"true" } :
                           String_Constant { L"false" };
                }
                template    <typename T>
                inline  String  ToString_ (const T& t, typename enable_if<is_same<T, signed char>::value>::type* = 0)
                {
                    wchar_t buf[1024];
                    (void)::swprintf (buf, NEltsOf (buf), L"%d", t);
                    return buf;
                }
                template    <typename T>
                inline  String  ToString_ (const T& t, typename enable_if<is_same<T, short int>::value>::type* = 0)
                {
                    wchar_t buf[1024];
                    (void)::swprintf (buf, NEltsOf (buf), L"%d", t);
                    return buf;
                }
                template    <typename T>
                inline  String  ToString_ (const T& t, typename enable_if<is_same<T, int>::value>::type* = 0)
                {
                    wchar_t buf[1024];
                    (void)::swprintf (buf, NEltsOf (buf), L"%d", t);
                    return buf;
                }
                template    <typename T>
                inline  String  ToString_ (const T& t, typename enable_if<is_same<T, long int>::value>::type* = 0)
                {
                    wchar_t buf[1024];
                    (void)::swprintf (buf, NEltsOf (buf), L"%ld", t);
                    return buf;
                }
                template    <typename T>
                inline  String  ToString_ (const T& t, typename enable_if<is_same<T, long long int>::value>::type* = 0)
                {
                    wchar_t buf[1024];
                    (void)::swprintf (buf, NEltsOf (buf), L"%lld", t);
                    return buf;
                }
                template    <typename T>
                inline  String  ToString_ (const T& t, typename enable_if<is_same<T, unsigned char>::value>::type* = 0)
                {
                    wchar_t buf[1024];
                    (void)::swprintf (buf, NEltsOf (buf), L"0x%x", t);
                    return buf;
                }
                template    <typename T>
                inline  String  ToString_ (const T& t, typename enable_if<is_same<T, unsigned short>::value>::type* = 0)
                {
                    wchar_t buf[1024];
                    (void)::swprintf (buf, NEltsOf (buf), L"0x%x", t);
                    return buf;
                }
                template    <typename T>
                inline  String  ToString_ (const T& t, typename enable_if<is_same<T, unsigned int>::value>::type* = 0)
                {
                    wchar_t buf[1024];
                    (void)::swprintf (buf, NEltsOf (buf), L"0x%x", t);
                    return buf;
                }
                template    <typename T>
                inline  String  ToString_ (const T& t, typename enable_if<is_same<T, unsigned long>::value>::type* = 0)
                {
                    wchar_t buf[1024];
                    (void)::swprintf (buf, NEltsOf (buf), L"0x%lx", t);
                    return buf;
                }
                template    <typename T>
                inline  String  ToString_ (const T& t, typename enable_if<is_same<T, unsigned long long>::value>::type* = 0)
                {
                    wchar_t buf[1024];
                    (void)::swprintf (buf, NEltsOf (buf), L"0x%llx", t);
                    return buf;
                }

                template    <typename T>
                inline  String  ToString_ (const T& t, typename enable_if < is_floating_point<T>::value>::type* = 0)
                {
                    return Float2String (t);
                }
            }

            template    <typename T>
            inline  String  ToString (const T& t)
            {
                return Private_::ToString_<T> (t);
            }

        }
    }
}
#endif  /*_Stroika_Foundation_Characters_ToString_inl_*/
<|endoftext|>


<commit_before>// Copyright 2014 RethinkDB, all rights reserved.
#ifndef CONCURRENCY_NEW_SEMAPHORE_HPP_
#define CONCURRENCY_NEW_SEMAPHORE_HPP_

#include "concurrency/cond_var.hpp"
#include "containers/intrusive_list.hpp"

// KSI: This is a horrible name, fix it.

class new_semaphore_acq_t;

class new_semaphore_t {
public:
    explicit new_semaphore_t(int64_t capacity);
    ~new_semaphore_t();

private:
    friend class new_semaphore_acq_t;
    void add_acquirer(new_semaphore_acq_t *acq);
    void remove_acquirer(new_semaphore_acq_t *acq);

    void pulse_waiters();

    int64_t capacity_;
    int64_t current_;

    intrusive_list_t<new_semaphore_acq_t> waiters_;

    DISABLE_COPYING(new_semaphore_t);
};

class new_semaphore_acq_t : public intrusive_list_node_t<new_semaphore_acq_t> {
public:
    // Construction is non-blocking, it gets you in line for the semaphore.  You need
    // to call acquisition()->wait() in order to wait for your acquisition of the
    // semaphore.  Acquirers receive the semaphore in the same order that they've
    // acquired it.
    ~new_semaphore_acq_t();
    new_semaphore_acq_t();
    new_semaphore_acq_t(new_semaphore_t *semaphore, int64_t count);

    void init(new_semaphore_t *semaphore, int64_t count);

    // Returns a signal that gets pulsed when this has successfully acquired the
    // semaphore.
    const signal_t *acquisition() const { return &cond_; }

private:
    friend class new_semaphore_t;

    // The semaphore this acquires (or NULL if this hasn't acquired a semaphore yet).
    new_semaphore_t *semaphore_;
    // The count of "how much" of the semaphore we've acquired (if semaphore_ is
    // non-NULL).
    int64_t count_;
    // Gets pulsed when we have successfully acquired the semaphore.
    cond_t cond_;
    DISABLE_COPYING(new_semaphore_acq_t);
};

#endif  // CONCURRENCY_NEW_SEMAPHORE_HPP_
<commit_msg>Added methods to new_semaphore_t.<commit_after>// Copyright 2014 RethinkDB, all rights reserved.
#ifndef CONCURRENCY_NEW_SEMAPHORE_HPP_
#define CONCURRENCY_NEW_SEMAPHORE_HPP_

#include "concurrency/cond_var.hpp"
#include "containers/intrusive_list.hpp"

// KSI: This is a horrible name, fix it.

class new_semaphore_acq_t;

class new_semaphore_t {
public:
    explicit new_semaphore_t(int64_t capacity);
    ~new_semaphore_t();

    int64_t capacity() const { return capacity_; }
    int64_t current() const { return current_; }

private:
    friend class new_semaphore_acq_t;
    void add_acquirer(new_semaphore_acq_t *acq);
    void remove_acquirer(new_semaphore_acq_t *acq);

    void pulse_waiters();

    int64_t capacity_;
    int64_t current_;

    intrusive_list_t<new_semaphore_acq_t> waiters_;

    DISABLE_COPYING(new_semaphore_t);
};

class new_semaphore_acq_t : public intrusive_list_node_t<new_semaphore_acq_t> {
public:
    // Construction is non-blocking, it gets you in line for the semaphore.  You need
    // to call acquisition()->wait() in order to wait for your acquisition of the
    // semaphore.  Acquirers receive the semaphore in the same order that they've
    // acquired it.
    ~new_semaphore_acq_t();
    new_semaphore_acq_t();
    new_semaphore_acq_t(new_semaphore_t *semaphore, int64_t count);

    void init(new_semaphore_t *semaphore, int64_t count);

    // Returns a signal that gets pulsed when this has successfully acquired the
    // semaphore.
    const signal_t *acquisition() const { return &cond_; }

private:
    friend class new_semaphore_t;

    // The semaphore this acquires (or NULL if this hasn't acquired a semaphore yet).
    new_semaphore_t *semaphore_;
    // The count of "how much" of the semaphore we've acquired (if semaphore_ is
    // non-NULL).
    int64_t count_;
    // Gets pulsed when we have successfully acquired the semaphore.
    cond_t cond_;
    DISABLE_COPYING(new_semaphore_acq_t);
};

#endif  // CONCURRENCY_NEW_SEMAPHORE_HPP_
<|endoftext|>


<commit_before>/***************************Copyright-DO-NOT-REMOVE-THIS-LINE**
  *
  * Condor Software Copyright Notice
  * Copyright (C) 1990-2006, Condor Team, Computer Sciences Department,
  * University of Wisconsin-Madison, WI.
  *
  * This source code is covered by the Condor Public License, which can
  * be found in the accompanying LICENSE.TXT file, or online at
  * www.condorproject.org.
  *
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  * AND THE UNIVERSITY OF WISCONSIN-MADISON "AS IS" AND ANY EXPRESS OR
  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  * WARRANTIES OF MERCHANTABILITY, OF SATISFACTORY QUALITY, AND FITNESS
  * FOR A PARTICULAR PURPOSE OR USE ARE DISCLAIMED. THE COPYRIGHT
  * HOLDERS AND CONTRIBUTORS AND THE UNIVERSITY OF WISCONSIN-MADISON
  * MAKE NO MAKE NO REPRESENTATION THAT THE SOFTWARE, MODIFICATIONS,
  * ENHANCEMENTS OR DERIVATIVE WORKS THEREOF, WILL NOT INFRINGE ANY
  * PATENT, COPYRIGHT, TRADEMARK, TRADE SECRET OR OTHER PROPRIETARY
  * RIGHT.
  *
  ****************************Copyright-DO-NOT-REMOVE-THIS-LINE**/

#include "condor_common.h"
#include "condor_debug.h"
#include "process_control.WINDOWS.h"
#include "ntsysinfo.h"
#include "HashTable.h"
#include "../condor_daemon_core.V6/condor_softkill.h"

static char* soft_kill_binary = NULL;

void
set_windows_soft_kill_binary(char* binary)
{
	if (soft_kill_binary != NULL) {
		free(soft_kill_binary);
	}
	soft_kill_binary = strdup(binary);
	ASSERT(soft_kill_binary != NULL);
}

bool
windows_soft_kill(DWORD pid)
{
	// softkill on Windows is implemented by posting a WM_CLOSE to
	// a top-level window owned by the process (if the process owns
	// more than 1 top-level window, it is undefined which one will
	// get the WM_CLOSE). finding the window and posting the message
	// are done using the condor_softkill tool
	//

	// bail out if the binary wasn't set
	//
	if (soft_kill_binary == NULL) {
		dprintf(D_ALWAYS,
		        "windows_soft_kill error: softkill binary not set\n");
		return false;
	}

	// construct the command line for the call to CreateProcess
	//
	char command_line[1024];
	command_line[1023] = '\0';
	int ret = snprintf(command_line,
	                   1024,
	                   "\"%s\" %u debug.txt",
	                   soft_kill_binary,
					   pid);
	if (ret < 0) {
		dprintf(D_ALWAYS,
		        "windows:soft_kill: snprintf error: %s (%d)\n",
		        strerror(errno),
		        errno);
		return false;
	}
	if (command_line[1023] != '\0') {
		dprintf(D_ALWAYS,
		        "windows_soft_kill: command line too long\n");
		return false;
	}

	// call CreateProcess to run the softkill executable
	//
	STARTUPINFO si;
	memset(&si, 0, sizeof(STARTUPINFO));
	PROCESS_INFORMATION pi;
	if (CreateProcess(NULL,         // get the executable from the command line
	                  command_line,
	                  NULL,         // default process security
	                  NULL,         // default security for primary thread
	                  FALSE,        // don't inherit handles
	                  0,            // no flags
	                  NULL,         // inherit our environment
	                  NULL,         // inherit our working directory
	                  &si,
	                  &pi) == FALSE)
	{
		dprintf(D_ALWAYS,
		        "windows_soft_kill: CreateProcess error: %u\n",
		        GetLastError());
		return false;
	}
	CloseHandle(pi.hThread);

	// wait for the exit code; fail if we can't get it or if
	// it indicates failure
	//
	if (WaitForSingleObject(pi.hProcess, INFINITE) != WAIT_OBJECT_0) {
		dprintf(D_ALWAYS,
		        "windows_soft_kill: WaitForSingleObject error: %u\n",
		        GetLastError());
	}
	DWORD exit_code;
	BOOL result = GetExitCodeProcess(pi.hProcess, &exit_code);
	DWORD error = GetLastError();
	CloseHandle(pi.hProcess);
	if (result == FALSE) {
		dprintf(D_ALWAYS,
		        "windows_soft_kill: GetExitCodeProcess error: %u\n",
		        GetLastError());
		return false;
	}
	if (exit_code != SOFTKILL_SUCCESS) {
		dprintf(D_ALWAYS,
		        "windows_soft_kill: error code from condor_softkill: %u\n",
		        exit_code);
		return false;
	}

	// i guess it worked
	//
	return true;
}

bool
windows_hard_kill(DWORD pid)
{
	HANDLE process = OpenProcess(PROCESS_TERMINATE, FALSE, pid);
	if (process == NULL) {
		dprintf(D_ALWAYS,
		        "windows_hard_kill: OpenProcess error: %u\n",
		        GetLastError());
		return false;
	}
	if (TerminateProcess(process, 0) == FALSE) {
		dprintf(D_ALWAYS,
		        "windows_hard_kill: TerminateProcess error: %u\n",
		        GetLastError());
		return false;
	}
	CloseHandle(process);

	return true;
}

// stupid hash function for DWORD (need by the hash tables
// used in the suspend/contiunue code below)
//
static int
hash_func(const DWORD& n, int num_buckets)
{
	return n % num_buckets;
}

// stupid object for getting the list of threads for a process
//
static CSysinfo sys_info;

// record to keep track of the threads in a suspended process
//
struct SuspendedThread {

	// cache a handle to each thread while the process is suspended
	//
	HANDLE handle;

	// how many suspends did we send this thread? (so we know how
	// many resumes to send!)
	//
	int num_suspends;
};

// for each suspended process we keep a hash table of its
// SuspendedThread structures (keyed on thread id)
//
typedef HashTable<DWORD, SuspendedThread*> SuspendedProcess;

// we keep track of all suspended processes via a hash table
// keyed on process id
//
static HashTable<DWORD, SuspendedProcess*> suspended_processes(11, hash_func);

bool
windows_suspend(DWORD pid)
{
	// make sure we haven't already suspended this process, then allocate
	// a SuspendedProcess object and add it to the hash table
	//
	SuspendedProcess* sp;
	int ret = suspended_processes.lookup(pid, sp);
	ASSERT(ret == -1);
	sp = new SuspendedProcess(11, hash_func);
	ASSERT(sp != NULL);
	ret = suspended_processes.insert(pid, sp);
	ASSERT(ret != -1);

	// we need to loop until iterating through the thread list for this
	// process shows that all threads are suspended
	//
	bool finished = false;
	while (!finished) {

		// assume we're going to succeed on this iteration until
		// proven otherwise
		//
		finished = true;

		// get the list of threads for this process
		//
		ExtArray<DWORD> tid_array;
		int num_tids = sys_info.GetTIDs(pid, tid_array);
		if (num_tids == 0) {
			// TODO: we need to handle this case!!!
			//
			EXCEPT("windows_suspend_process failed: can't get threads for pid %u",
			       pid);
		}

		// go through the thread list, calling SuspendThread on each
		//
		for (int i = 0; i < num_tids; i++) {

			// see if we already have a record for this thread
			//
			SuspendedThread* st;
			ret = sp->lookup(tid_array[i], st);
			if (ret == -1) {

				// no record yet; open up this thread's handle
				//
				HANDLE handle = OpenThread(THREAD_SUSPEND_RESUME, FALSE, tid_array[i]);
				if (handle == NULL) {

					// the thread probably exited; however, it may have called ResumeThread
					// or CreateThread first, so we'll have to loop again
					//
					finished = false;
					dprintf(D_FULLDEBUG,
					        "windows_suspend_process: OpenThread error: %u\n",
					        GetLastError());
					continue;
				}

				// now that we have a handle, create a record for this thread
				//
				st = new SuspendedThread;
				ASSERT(st != NULL);
				st->handle = handle;
				st->num_suspends = 0;
			}

			// now suspend the thread
			//
			DWORD result = SuspendThread(st->handle);
			if (result == (DWORD)-1) {

				// how can this happen? maybe the thread exited?
				//
				finished = false;
				dprintf(D_FULLDEBUG,
						"windows_suspend_process: SuspendThread error: %u\n",
						GetLastError());
				continue;
			}

			// if the thread was not suspended prior to our SuspendThread call,
			// it may have called CreateThread or ResumeThread so we need to loop
			// at least one more time
			//
			if (result == 0) {
				finished = false;
			}

			// keep track of how many suspends we've sent this thread
			//
			st->num_suspends++;
		}
	}

	return true;
}

bool
windows_continue(DWORD pid)
{
	// we should have a record from when we suspended this process
	//
	SuspendedProcess* sp;
	int ret = suspended_processes.lookup(pid, sp);
	ASSERT(ret != -1);

	SuspendedThread* st;
	sp->startIterations();
	while (sp->iterate(st)) {

		// call ResumeThread as many times as we called SuspendThread
		// for this thread above
		//
		for (int i = 0; i < st->num_suspends; i++) {
			if (ResumeThread(st->handle) == (DWORD)-1) {
				dprintf(D_FULLDEBUG,
				        "windows_continue_process: ResumeThread error: %u\n",
				        GetLastError());
			}
		}

		// close our handle to this thread
		//
		if (CloseHandle(st->handle) == FALSE) {
			dprintf(D_FULLDEBUG,
			        "windows_continue_process: CloseHandle error: %u\n",
			        GetLastError());
		}

		// clean up this SuspendedThread object
		//
		delete st;
	}

	// clean up the SuspendedProcess object and remove it from the
	// hash table of processes
	//
	delete sp;
	ret = suspended_processes.remove(pid);
	ASSERT(ret != -1);

	return true;
}<commit_msg>Fix hash function to match new function prototype for HashTabling hashing function.<commit_after>/***************************Copyright-DO-NOT-REMOVE-THIS-LINE**
  *
  * Condor Software Copyright Notice
  * Copyright (C) 1990-2006, Condor Team, Computer Sciences Department,
  * University of Wisconsin-Madison, WI.
  *
  * This source code is covered by the Condor Public License, which can
  * be found in the accompanying LICENSE.TXT file, or online at
  * www.condorproject.org.
  *
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  * AND THE UNIVERSITY OF WISCONSIN-MADISON "AS IS" AND ANY EXPRESS OR
  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  * WARRANTIES OF MERCHANTABILITY, OF SATISFACTORY QUALITY, AND FITNESS
  * FOR A PARTICULAR PURPOSE OR USE ARE DISCLAIMED. THE COPYRIGHT
  * HOLDERS AND CONTRIBUTORS AND THE UNIVERSITY OF WISCONSIN-MADISON
  * MAKE NO MAKE NO REPRESENTATION THAT THE SOFTWARE, MODIFICATIONS,
  * ENHANCEMENTS OR DERIVATIVE WORKS THEREOF, WILL NOT INFRINGE ANY
  * PATENT, COPYRIGHT, TRADEMARK, TRADE SECRET OR OTHER PROPRIETARY
  * RIGHT.
  *
  ****************************Copyright-DO-NOT-REMOVE-THIS-LINE**/

#include "condor_common.h"
#include "condor_debug.h"
#include "process_control.WINDOWS.h"
#include "ntsysinfo.h"
#include "HashTable.h"
#include "../condor_daemon_core.V6/condor_softkill.h"

static char* soft_kill_binary = NULL;

void
set_windows_soft_kill_binary(char* binary)
{
	if (soft_kill_binary != NULL) {
		free(soft_kill_binary);
	}
	soft_kill_binary = strdup(binary);
	ASSERT(soft_kill_binary != NULL);
}

bool
windows_soft_kill(DWORD pid)
{
	// softkill on Windows is implemented by posting a WM_CLOSE to
	// a top-level window owned by the process (if the process owns
	// more than 1 top-level window, it is undefined which one will
	// get the WM_CLOSE). finding the window and posting the message
	// are done using the condor_softkill tool
	//

	// bail out if the binary wasn't set
	//
	if (soft_kill_binary == NULL) {
		dprintf(D_ALWAYS,
		        "windows_soft_kill error: softkill binary not set\n");
		return false;
	}

	// construct the command line for the call to CreateProcess
	//
	char command_line[1024];
	command_line[1023] = '\0';
	int ret = snprintf(command_line,
	                   1024,
	                   "\"%s\" %u debug.txt",
	                   soft_kill_binary,
					   pid);
	if (ret < 0) {
		dprintf(D_ALWAYS,
		        "windows:soft_kill: snprintf error: %s (%d)\n",
		        strerror(errno),
		        errno);
		return false;
	}
	if (command_line[1023] != '\0') {
		dprintf(D_ALWAYS,
		        "windows_soft_kill: command line too long\n");
		return false;
	}

	// call CreateProcess to run the softkill executable
	//
	STARTUPINFO si;
	memset(&si, 0, sizeof(STARTUPINFO));
	PROCESS_INFORMATION pi;
	if (CreateProcess(NULL,         // get the executable from the command line
	                  command_line,
	                  NULL,         // default process security
	                  NULL,         // default security for primary thread
	                  FALSE,        // don't inherit handles
	                  0,            // no flags
	                  NULL,         // inherit our environment
	                  NULL,         // inherit our working directory
	                  &si,
	                  &pi) == FALSE)
	{
		dprintf(D_ALWAYS,
		        "windows_soft_kill: CreateProcess error: %u\n",
		        GetLastError());
		return false;
	}
	CloseHandle(pi.hThread);

	// wait for the exit code; fail if we can't get it or if
	// it indicates failure
	//
	if (WaitForSingleObject(pi.hProcess, INFINITE) != WAIT_OBJECT_0) {
		dprintf(D_ALWAYS,
		        "windows_soft_kill: WaitForSingleObject error: %u\n",
		        GetLastError());
	}
	DWORD exit_code;
	BOOL result = GetExitCodeProcess(pi.hProcess, &exit_code);
	DWORD error = GetLastError();
	CloseHandle(pi.hProcess);
	if (result == FALSE) {
		dprintf(D_ALWAYS,
		        "windows_soft_kill: GetExitCodeProcess error: %u\n",
		        GetLastError());
		return false;
	}
	if (exit_code != SOFTKILL_SUCCESS) {
		dprintf(D_ALWAYS,
		        "windows_soft_kill: error code from condor_softkill: %u\n",
		        exit_code);
		return false;
	}

	// i guess it worked
	//
	return true;
}

bool
windows_hard_kill(DWORD pid)
{
	HANDLE process = OpenProcess(PROCESS_TERMINATE, FALSE, pid);
	if (process == NULL) {
		dprintf(D_ALWAYS,
		        "windows_hard_kill: OpenProcess error: %u\n",
		        GetLastError());
		return false;
	}
	if (TerminateProcess(process, 0) == FALSE) {
		dprintf(D_ALWAYS,
		        "windows_hard_kill: TerminateProcess error: %u\n",
		        GetLastError());
		return false;
	}
	CloseHandle(process);

	return true;
}

// stupid hash function for DWORD (need by the hash tables
// used in the suspend/contiunue code below)
//
static unsigned int
hash_func(const DWORD& n)
{
	return n;
}

// stupid object for getting the list of threads for a process
//
static CSysinfo sys_info;

// record to keep track of the threads in a suspended process
//
struct SuspendedThread {

	// cache a handle to each thread while the process is suspended
	//
	HANDLE handle;

	// how many suspends did we send this thread? (so we know how
	// many resumes to send!)
	//
	int num_suspends;
};

// for each suspended process we keep a hash table of its
// SuspendedThread structures (keyed on thread id)
//
typedef HashTable<DWORD, SuspendedThread*> SuspendedProcess;

// we keep track of all suspended processes via a hash table
// keyed on process id
//
static HashTable<DWORD, SuspendedProcess*> suspended_processes(11, hash_func);

bool
windows_suspend(DWORD pid)
{
	// make sure we haven't already suspended this process, then allocate
	// a SuspendedProcess object and add it to the hash table
	//
	SuspendedProcess* sp;
	int ret = suspended_processes.lookup(pid, sp);
	ASSERT(ret == -1);
	sp = new SuspendedProcess(11, hash_func);
	ASSERT(sp != NULL);
	ret = suspended_processes.insert(pid, sp);
	ASSERT(ret != -1);

	// we need to loop until iterating through the thread list for this
	// process shows that all threads are suspended
	//
	bool finished = false;
	while (!finished) {

		// assume we're going to succeed on this iteration until
		// proven otherwise
		//
		finished = true;

		// get the list of threads for this process
		//
		ExtArray<DWORD> tid_array;
		int num_tids = sys_info.GetTIDs(pid, tid_array);
		if (num_tids == 0) {
			// TODO: we need to handle this case!!!
			//
			EXCEPT("windows_suspend_process failed: can't get threads for pid %u",
			       pid);
		}

		// go through the thread list, calling SuspendThread on each
		//
		for (int i = 0; i < num_tids; i++) {

			// see if we already have a record for this thread
			//
			SuspendedThread* st;
			ret = sp->lookup(tid_array[i], st);
			if (ret == -1) {

				// no record yet; open up this thread's handle
				//
				HANDLE handle = OpenThread(THREAD_SUSPEND_RESUME, FALSE, tid_array[i]);
				if (handle == NULL) {

					// the thread probably exited; however, it may have called ResumeThread
					// or CreateThread first, so we'll have to loop again
					//
					finished = false;
					dprintf(D_FULLDEBUG,
					        "windows_suspend_process: OpenThread error: %u\n",
					        GetLastError());
					continue;
				}

				// now that we have a handle, create a record for this thread
				//
				st = new SuspendedThread;
				ASSERT(st != NULL);
				st->handle = handle;
				st->num_suspends = 0;
			}

			// now suspend the thread
			//
			DWORD result = SuspendThread(st->handle);
			if (result == (DWORD)-1) {

				// how can this happen? maybe the thread exited?
				//
				finished = false;
				dprintf(D_FULLDEBUG,
						"windows_suspend_process: SuspendThread error: %u\n",
						GetLastError());
				continue;
			}

			// if the thread was not suspended prior to our SuspendThread call,
			// it may have called CreateThread or ResumeThread so we need to loop
			// at least one more time
			//
			if (result == 0) {
				finished = false;
			}

			// keep track of how many suspends we've sent this thread
			//
			st->num_suspends++;
		}
	}

	return true;
}

bool
windows_continue(DWORD pid)
{
	// we should have a record from when we suspended this process
	//
	SuspendedProcess* sp;
	int ret = suspended_processes.lookup(pid, sp);
	ASSERT(ret != -1);

	SuspendedThread* st;
	sp->startIterations();
	while (sp->iterate(st)) {

		// call ResumeThread as many times as we called SuspendThread
		// for this thread above
		//
		for (int i = 0; i < st->num_suspends; i++) {
			if (ResumeThread(st->handle) == (DWORD)-1) {
				dprintf(D_FULLDEBUG,
				        "windows_continue_process: ResumeThread error: %u\n",
				        GetLastError());
			}
		}

		// close our handle to this thread
		//
		if (CloseHandle(st->handle) == FALSE) {
			dprintf(D_FULLDEBUG,
			        "windows_continue_process: CloseHandle error: %u\n",
			        GetLastError());
		}

		// clean up this SuspendedThread object
		//
		delete st;
	}

	// clean up the SuspendedProcess object and remove it from the
	// hash table of processes
	//
	delete sp;
	ret = suspended_processes.remove(pid);
	ASSERT(ret != -1);

	return true;
}
<|endoftext|>


<commit_before>#pragma once

#include "boost_defs.hpp"

#include "gcd_utility.hpp"
#include "grabbable_state_manager.hpp"
#include "grabber_client.hpp"
#include "hid_manager.hpp"
#include "hid_observer.hpp"
#include "logger.hpp"
#include "types.hpp"

namespace krbn {
class device_observer final {
public:
  device_observer(const device_observer&) = delete;

  device_observer(const grabber_client& grabber_client) : grabber_client_(grabber_client),
                                                          hid_manager_({
                                                              std::make_pair(hid_usage_page::generic_desktop, hid_usage::gd_keyboard),
                                                              std::make_pair(hid_usage_page::generic_desktop, hid_usage::gd_mouse),
                                                              std::make_pair(hid_usage_page::generic_desktop, hid_usage::gd_pointer),
                                                          }) {
    grabbable_state_manager_.grabbable_state_changed.connect([this](auto&& registry_entry_id,
                                                                    auto&& grabbable_state,
                                                                    auto&& ungrabbable_temporarily_reason,
                                                                    auto&& time_stamp) {
      grabber_client_.grabbable_state_changed(registry_entry_id,
                                              grabbable_state,
                                              ungrabbable_temporarily_reason,
                                              time_stamp);
    });

    hid_manager_.device_detecting.connect([](auto&& device) {
      if (iokit_utility::is_karabiner_virtual_hid_device(device)) {
        return false;
      }

      iokit_utility::log_matching_device(device);

      return true;
    });

    hid_manager_.device_detected.connect([this](auto&& human_interface_device) {
      logger::get_logger().info("{0} is detected.", human_interface_device->get_name_for_log());

      grabbable_state_manager_.update(human_interface_device->get_registry_entry_id(),
                                      grabbable_state::device_error,
                                      ungrabbable_temporarily_reason::none,
                                      mach_absolute_time());

      human_interface_device->values_arrived.connect([this](auto&& human_interface_device,
                                                            auto&& event_queue) {
        grabbable_state_manager_.update(event_queue);
      });

      auto observer = std::make_shared<hid_observer>(human_interface_device);
      observer->device_observed.connect([this](auto&& human_interface_device) {
        logger::get_logger().info("{0} is observed.",
                                  human_interface_device->get_name_for_log());

        if (auto state = grabbable_state_manager_.get_grabbable_state(human_interface_device->get_registry_entry_id())) {
          // Keep grabbable_state if the state is already changed by value_callback.
          if (state->first == grabbable_state::device_error) {
            grabbable_state_manager_.update(human_interface_device->get_registry_entry_id(),
                                            grabbable_state::grabbable,
                                            ungrabbable_temporarily_reason::none,
                                            mach_absolute_time());
          }
        }
      });

      observer->observe();

      hid_observers_[human_interface_device->get_registry_entry_id()] = observer;
    });

    hid_manager_.device_removed.connect([](auto&& human_interface_device) {
      logger::get_logger().info("{0} is removed.", human_interface_device->get_name_for_log());
    });

    hid_manager_.start();
  }

  ~device_observer(void) {
    hid_observers_.clear();
    hid_manager_.stop();
  }

private:
  const grabber_client& grabber_client_;

  hid_manager hid_manager_;
  std::unordered_map<registry_entry_id, std::shared_ptr<hid_observer>> hid_observers_;
  grabbable_state_manager grabbable_state_manager_;
};
} // namespace krbn
<commit_msg>erase hid_observer in device_removed<commit_after>#pragma once

#include "boost_defs.hpp"

#include "gcd_utility.hpp"
#include "grabbable_state_manager.hpp"
#include "grabber_client.hpp"
#include "hid_manager.hpp"
#include "hid_observer.hpp"
#include "logger.hpp"
#include "types.hpp"

namespace krbn {
class device_observer final {
public:
  device_observer(const device_observer&) = delete;

  device_observer(const grabber_client& grabber_client) : grabber_client_(grabber_client),
                                                          hid_manager_({
                                                              std::make_pair(hid_usage_page::generic_desktop, hid_usage::gd_keyboard),
                                                              std::make_pair(hid_usage_page::generic_desktop, hid_usage::gd_mouse),
                                                              std::make_pair(hid_usage_page::generic_desktop, hid_usage::gd_pointer),
                                                          }) {
    grabbable_state_manager_.grabbable_state_changed.connect([this](auto&& registry_entry_id,
                                                                    auto&& grabbable_state,
                                                                    auto&& ungrabbable_temporarily_reason,
                                                                    auto&& time_stamp) {
      grabber_client_.grabbable_state_changed(registry_entry_id,
                                              grabbable_state,
                                              ungrabbable_temporarily_reason,
                                              time_stamp);
    });

    hid_manager_.device_detecting.connect([](auto&& device) {
      if (iokit_utility::is_karabiner_virtual_hid_device(device)) {
        return false;
      }

      iokit_utility::log_matching_device(device);

      return true;
    });

    hid_manager_.device_detected.connect([this](auto&& human_interface_device) {
      logger::get_logger().info("{0} is detected.", human_interface_device->get_name_for_log());

      grabbable_state_manager_.update(human_interface_device->get_registry_entry_id(),
                                      grabbable_state::device_error,
                                      ungrabbable_temporarily_reason::none,
                                      mach_absolute_time());

      human_interface_device->values_arrived.connect([this](auto&& human_interface_device,
                                                            auto&& event_queue) {
        grabbable_state_manager_.update(event_queue);
      });

      auto observer = std::make_shared<hid_observer>(human_interface_device);
      observer->device_observed.connect([this](auto&& human_interface_device) {
        logger::get_logger().info("{0} is observed.",
                                  human_interface_device->get_name_for_log());

        if (auto state = grabbable_state_manager_.get_grabbable_state(human_interface_device->get_registry_entry_id())) {
          // Keep grabbable_state if the state is already changed by value_callback.
          if (state->first == grabbable_state::device_error) {
            grabbable_state_manager_.update(human_interface_device->get_registry_entry_id(),
                                            grabbable_state::grabbable,
                                            ungrabbable_temporarily_reason::none,
                                            mach_absolute_time());
          }
        }
      });

      observer->observe();

      hid_observers_[human_interface_device->get_registry_entry_id()] = observer;
    });

    hid_manager_.device_removed.connect([this](auto&& human_interface_device) {
      logger::get_logger().info("{0} is removed.", human_interface_device->get_name_for_log());

      hid_observers_.erase(human_interface_device->get_registry_entry_id());
    });

    hid_manager_.start();
  }

  ~device_observer(void) {
    hid_observers_.clear();
    hid_manager_.stop();
  }

private:
  const grabber_client& grabber_client_;

  hid_manager hid_manager_;
  std::unordered_map<registry_entry_id, std::shared_ptr<hid_observer>> hid_observers_;
  grabbable_state_manager grabbable_state_manager_;
};
} // namespace krbn
<|endoftext|>