<commit_before>#include <mtp/ptp/Device.h>
#include <mtp/ptp/Response.h>
#include <mtp/ptp/Container.h>
#include <mtp/usb/Context.h>
#include <mtp/ptp/OperationRequest.h>

namespace mtp
{
	msg::ObjectHandles Session::GetObjectHandles(u32 storageId, u32 objectFormat, u32 parent)
	{
		OperationRequest req(OperationCode::GetObjectHandles, _transactionId++, storageId, objectFormat, parent);
		Container container(req);
		_packeter.Write(container.Data);
		ByteArray data = _packeter.Read();
		Stream stream(data, 8); //operation code + session id

		msg::ObjectHandles goh;
		goh.Read(stream);
		return std::move(goh);
	}
	msg::StorageIDs Session::GetStorageIDs()
	{
		OperationRequest req(OperationCode::GetStorageIDs, _transactionId++, 0xffffffffu);
		Container container(req);
		_packeter.Write(container.Data);
		ByteArray data = _packeter.Read();
		Stream stream(data, 8); //operation code + session id

		msg::StorageIDs gsi;
		gsi.Read(stream);
		return std::move(gsi);
	}

	msg::StorageInfo Session::GetStorageInfo(u32 storageId)
	{
		OperationRequest req(OperationCode::GetStorageInfo, _transactionId++, storageId);
		Container container(req);
		_packeter.Write(container.Data);
		ByteArray data = _packeter.Read();
		Stream stream(data, 8); //operation code + session id
		msg::StorageInfo gsi;
		gsi.Read(stream);
		return std::move(gsi);
	}

	msg::ObjectInfo Session::GetObjectInfo(u32 objectId)
	{
		OperationRequest req(OperationCode::GetObjectInfo, _transactionId++, objectId);
		Container container(req);
		_packeter.Write(container.Data);
		ByteArray data = _packeter.Read();
		Stream stream(data, 8); //operation code + session id
		msg::ObjectInfo goi;
		goi.Read(stream);
		return std::move(goi);
	}

	msg::DeviceInfo Device::GetDeviceInfo()
	{
		OperationRequest req(OperationCode::GetDeviceInfo);
		Container container(req);
		_packeter.Write(container.Data);
		ByteArray data = _packeter.Read();
		HexDump("payload", data);

		Stream stream(data, 8); //operation code + session id
		msg::DeviceInfo gdi;
		gdi.Read(stream);
		return std::move(gdi);
	}

	SessionPtr Device::OpenSession(u32 sessionId)
	{
		OperationRequest req(OperationCode::OpenSession, 0, sessionId);
		Container container(req);
		_packeter.Write(container.Data);
		ByteArray data = _packeter.Read();
		HexDump("payload", data);

		return std::make_shared<Session>(_packeter.GetPipe(), sessionId);
	}

	void PipePacketer::Write(const ByteArray &data)
	{
		HexDump("send", data);
		_pipe->Write(data);
	}

	ByteArray PipePacketer::ReadMessage()
	{
		ByteArray result;
		u32 size = ~0u;
		size_t offset = 0;
		size_t packet_offset;
		while(true)
		{
			ByteArray data = _pipe->Read();
			if (size == ~0u)
			{
				Stream stream(data);
				stream >> size;
				printf("DATA SIZE = %u\n", size);
				if (size < 4)
					throw std::runtime_error("invalid size");
				packet_offset = 4;
				result.resize(size - 4);
			}
			else
				packet_offset = 0;
			HexDump("recv", data);

			size_t src_n = std::min(data.size() - packet_offset, result.size() - offset);
			std::copy(data.begin() + packet_offset, data.begin() + packet_offset + src_n, result.begin() + offset);
			offset += data.size();
			if (offset >= result.size())
				break;
		}
		return result;

	}

	ByteArray PipePacketer::Read()
	{
		_pipe->ReadInterrupt();
		ByteArray message = ReadMessage();
		HexDump("message", message);
		Stream stream(message);
		u16 raw_code;
		stream >> raw_code;
		ContainerType type = ContainerType(raw_code);
		if (type == ContainerType::Response)
			return ByteArray();

		ByteArray response = ReadMessage();
		HexDump("response", response);
		return message;
	}

	DevicePtr Device::Find()
	{
		using namespace mtp;
		usb::ContextPtr ctx(new usb::Context);

		int mtp_configuration = -1;
		int mtp_interface = -1;

		usb::ConfigurationPtr		configuration;
		usb::InterfacePtr			interface;
		usb::DevicePtr				device;

		for (usb::DeviceDescriptorPtr desc : ctx->GetDevices())
		{
			device = desc->TryOpen(ctx);
			if (!device)
				continue;
			int confs = desc->GetConfigurationsCount();
			printf("configurations: %d\n", confs);

			for(int i = 0; i < confs; ++i)
			{
				usb::ConfigurationPtr conf = desc->GetConfiguration(i);
				int interfaces = conf->GetInterfaceCount();
				printf("interfaces: %d\n", interfaces);
				for(int j = 0; j < interfaces; ++j)
				{
					usb::InterfacePtr iface = conf->GetInterface(conf, j, 0);
					printf("%d:%d index %u, eps %u\n", i, j, iface->GetIndex(), iface->GetEndpointsCount());
					int name_idx = iface->GetNameIndex();
					if (!name_idx)
						continue;
					std::string name = device->GetString(name_idx);
					if (name == "MTP")
					{
						configuration = conf;
						interface = iface;
						mtp_configuration = i;
						mtp_interface = j;
						i = confs;
						break;
					}
				}
			}
		}

		if (!interface || mtp_interface < 0 || mtp_configuration < 0)
			return nullptr;

		//device->SetConfiguration(configuration->GetIndex());
		usb::BulkPipePtr pipe = usb::BulkPipe::Create(device, interface);
		return std::make_shared<Device>(pipe);
	}

}
<commit_msg>cleaned up discovery code<commit_after>#include <mtp/ptp/Device.h>
#include <mtp/ptp/Response.h>
#include <mtp/ptp/Container.h>
#include <mtp/usb/Context.h>
#include <mtp/ptp/OperationRequest.h>

namespace mtp
{
	msg::ObjectHandles Session::GetObjectHandles(u32 storageId, u32 objectFormat, u32 parent)
	{
		OperationRequest req(OperationCode::GetObjectHandles, _transactionId++, storageId, objectFormat, parent);
		Container container(req);
		_packeter.Write(container.Data);
		ByteArray data = _packeter.Read();
		Stream stream(data, 8); //operation code + session id

		msg::ObjectHandles goh;
		goh.Read(stream);
		return std::move(goh);
	}
	msg::StorageIDs Session::GetStorageIDs()
	{
		OperationRequest req(OperationCode::GetStorageIDs, _transactionId++, 0xffffffffu);
		Container container(req);
		_packeter.Write(container.Data);
		ByteArray data = _packeter.Read();
		Stream stream(data, 8); //operation code + session id

		msg::StorageIDs gsi;
		gsi.Read(stream);
		return std::move(gsi);
	}

	msg::StorageInfo Session::GetStorageInfo(u32 storageId)
	{
		OperationRequest req(OperationCode::GetStorageInfo, _transactionId++, storageId);
		Container container(req);
		_packeter.Write(container.Data);
		ByteArray data = _packeter.Read();
		Stream stream(data, 8); //operation code + session id
		msg::StorageInfo gsi;
		gsi.Read(stream);
		return std::move(gsi);
	}

	msg::ObjectInfo Session::GetObjectInfo(u32 objectId)
	{
		OperationRequest req(OperationCode::GetObjectInfo, _transactionId++, objectId);
		Container container(req);
		_packeter.Write(container.Data);
		ByteArray data = _packeter.Read();
		Stream stream(data, 8); //operation code + session id
		msg::ObjectInfo goi;
		goi.Read(stream);
		return std::move(goi);
	}

	msg::DeviceInfo Device::GetDeviceInfo()
	{
		OperationRequest req(OperationCode::GetDeviceInfo);
		Container container(req);
		_packeter.Write(container.Data);
		ByteArray data = _packeter.Read();
		HexDump("payload", data);

		Stream stream(data, 8); //operation code + session id
		msg::DeviceInfo gdi;
		gdi.Read(stream);
		return std::move(gdi);
	}

	SessionPtr Device::OpenSession(u32 sessionId)
	{
		OperationRequest req(OperationCode::OpenSession, 0, sessionId);
		Container container(req);
		_packeter.Write(container.Data);
		ByteArray data = _packeter.Read();
		HexDump("payload", data);

		return std::make_shared<Session>(_packeter.GetPipe(), sessionId);
	}

	void PipePacketer::Write(const ByteArray &data)
	{
		HexDump("send", data);
		_pipe->Write(data);
	}

	ByteArray PipePacketer::ReadMessage()
	{
		ByteArray result;
		u32 size = ~0u;
		size_t offset = 0;
		size_t packet_offset;
		while(true)
		{
			ByteArray data = _pipe->Read();
			if (size == ~0u)
			{
				Stream stream(data);
				stream >> size;
				printf("DATA SIZE = %u\n", size);
				if (size < 4)
					throw std::runtime_error("invalid size");
				packet_offset = 4;
				result.resize(size - 4);
			}
			else
				packet_offset = 0;
			HexDump("recv", data);

			size_t src_n = std::min(data.size() - packet_offset, result.size() - offset);
			std::copy(data.begin() + packet_offset, data.begin() + packet_offset + src_n, result.begin() + offset);
			offset += data.size();
			if (offset >= result.size())
				break;
		}
		return result;

	}

	ByteArray PipePacketer::Read()
	{
		_pipe->ReadInterrupt();
		ByteArray message = ReadMessage();
		HexDump("message", message);
		Stream stream(message);
		u16 raw_code;
		stream >> raw_code;
		ContainerType type = ContainerType(raw_code);
		if (type == ContainerType::Response)
			return ByteArray();

		ByteArray response = ReadMessage();
		HexDump("response", response);
		return message;
	}

	DevicePtr Device::Find()
	{
		using namespace mtp;
		usb::ContextPtr ctx(new usb::Context);

		for (usb::DeviceDescriptorPtr desc : ctx->GetDevices())
		{
			usb::DevicePtr device = desc->TryOpen(ctx);
			if (!device)
				continue;
			int confs = desc->GetConfigurationsCount();
			printf("configurations: %d\n", confs);

			for(int i = 0; i < confs; ++i)
			{
				usb::ConfigurationPtr conf = desc->GetConfiguration(i);
				int interfaces = conf->GetInterfaceCount();
				printf("interfaces: %d\n", interfaces);
				for(int j = 0; j < interfaces; ++j)
				{
					usb::InterfacePtr iface = conf->GetInterface(conf, j, 0);
					printf("%d:%d index %u, eps %u\n", i, j, iface->GetIndex(), iface->GetEndpointsCount());
					int name_idx = iface->GetNameIndex();
					if (!name_idx)
						continue;
					std::string name = device->GetString(name_idx);
					if (name == "MTP")
					{
						//device->SetConfiguration(configuration->GetIndex());
						usb::BulkPipePtr pipe = usb::BulkPipe::Create(device, iface);
						return std::make_shared<Device>(pipe);
						break;
					}
				}
			}
		}

		return nullptr;
	}

}
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the examples of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:BSD$
** You may use this file under the terms of the BSD license as follows:
**
** "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 Nokia Corporation and its Subsidiary(-ies) 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
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
** $QT_END_LICENSE$
**
****************************************************************************/

#include <QtCore>
#include <qmagnetometer.h>

QTM_USE_NAMESPACE

class MagGeoFilter : public QMagnetometerFilter
{
public:
    qtimestamp stamp;
    bool filter(QMagnetometerReading *reading)
    {
        int diff = ( reading->timestamp() - stamp );
        stamp = reading->timestamp();
        QTextStream out(stdout);
        out << QString("Geomagnetic flux density: %1 x").arg(reading->x() * 1000000, 6, 'f', 1)
            << QString(" %1 y").arg(reading->y() * 1000000, 6, 'f', 1)
            << QString(" %1 z uT").arg(reading->z() * 1000000, 6, 'f', 1)
            << QString(" calibration: %1").arg(reading->calibrationLevel(), 3, 'f', 1)
            << QString(" (%1 ms since last, %2 Hz)").arg(diff / 1000, 4).arg( 1000000.0 / diff, 4, 'f', 1) << endl;
        return false;
    }
};

class MagRawFilter : public QMagnetometerFilter
{
public:
    qtimestamp stamp;
    bool filter(QMagnetometerReading *reading)
    {
        int diff = ( reading->timestamp() - stamp );
        stamp = reading->timestamp();
        QTextStream out(stdout);
        out << QString("Raw magnetic flux density: %1 x").arg(reading->x() * 1000000, 6, 'f', 1)
            << QString(" %1 y").arg(reading->y() * 1000000, 6, 'f', 1)
            << QString(" %1 z uT").arg(reading->z() * 1000000, 6, 'f', 1)
            << QString(" calibration: %1").arg(reading->calibrationLevel(), 3, 'f', 1)
            << QString(" (%1 ms since last, %2 Hz)").arg(diff / 1000, 4).arg( 1000000.0 / diff, 4, 'f', 1) << endl;
        return false;
    }
};

int main(int argc, char **argv)
{
    QCoreApplication app(argc, argv);
    QStringList args = app.arguments();
    int rate_place = args.indexOf("-r");
    int rate_val = 0;
    if (rate_place != -1)
        rate_val = args.at(rate_place + 1).toInt();

    QMagnetometer geosensor;
    geosensor.connectToBackend();

    int buffer_place = args.indexOf("-b");
    int bufferSize = buffer_place!=-1? args.at(buffer_place + 1).toInt():1;
    geosensor.setProperty("bufferSize",bufferSize);

    if (rate_val > 0) {
        geosensor.setDataRate(rate_val);
    }
    MagGeoFilter geofilter;
    geosensor.setProperty("returnGeoValues", true);
    geosensor.addFilter(&geofilter);
    geosensor.start();
    if (!geosensor.isActive()) {
        qWarning("Magnetometersensor (geo) didn't start!");
        return 1;
    }

    QMagnetometer rawsensor;
    if (rate_val > 0) {
        rawsensor.setDataRate(rate_val);
    }
    MagRawFilter rawfilter;
    rawsensor.addFilter(&rawfilter);
    qDebug() << rawsensor.availableDataRates().size();
    rawsensor.start();
    if (!rawsensor.isActive()) {
        qWarning("Magnetometersensor (raw) didn't start!");
        return 1;
    }

    return app.exec();
}
<commit_msg>connectToBackend missing<commit_after>/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the examples of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:BSD$
** You may use this file under the terms of the BSD license as follows:
**
** "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 Nokia Corporation and its Subsidiary(-ies) 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
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
** $QT_END_LICENSE$
**
****************************************************************************/

#include <QtCore>
#include <qmagnetometer.h>

QTM_USE_NAMESPACE

namespace check{
    static void checkRate(QSensor* sensor, int rate){
        qDebug()<<"data rate set for sensor "<<rate;
        if (rate == sensor->dataRate()) return;
        if (rate!=sensor->dataRate()){
            qrangelist rates = sensor->availableDataRates();
            QString datarates;
            for( int i = 0; i < rates.size(); ++i )
            {
                datarates.append("[");
                QString num;
                datarates.append(num.setNum(rates[i].first));
                datarates.append("..");
                datarates.append(num.setNum(rates[i].second));
                datarates.append("] ");
            }
            qDebug()<<"Rate setting failed, rate must be within range "<<datarates;
        }
    }
}

class MagGeoFilter : public QMagnetometerFilter
{
public:
    qtimestamp stamp;
    bool filter(QMagnetometerReading *reading)
    {
        int diff = ( reading->timestamp() - stamp );
        stamp = reading->timestamp();
        QTextStream out(stdout);
        out << QString("Geomagnetic flux density: %1 x").arg(reading->x() * 1000000, 6, 'f', 1)
            << QString(" %1 y").arg(reading->y() * 1000000, 6, 'f', 1)
            << QString(" %1 z uT").arg(reading->z() * 1000000, 6, 'f', 1)
            << QString(" calibration: %1").arg(reading->calibrationLevel(), 3, 'f', 1)
            << QString(" (%1 ms since last, %2 Hz)").arg(diff / 1000, 4).arg( 1000000.0 / diff, 4, 'f', 1) << endl;
        return false;
    }
};

class MagRawFilter : public QMagnetometerFilter
{
public:
    qtimestamp stamp;
    bool filter(QMagnetometerReading *reading)
    {
        int diff = ( reading->timestamp() - stamp );
        stamp = reading->timestamp();
        QTextStream out(stdout);
        out << QString("Raw magnetic flux density: %1 x").arg(reading->x() * 1000000, 6, 'f', 1)
            << QString(" %1 y").arg(reading->y() * 1000000, 6, 'f', 1)
            << QString(" %1 z uT").arg(reading->z() * 1000000, 6, 'f', 1)
            << QString(" calibration: %1").arg(reading->calibrationLevel(), 3, 'f', 1)
            << QString(" (%1 ms since last, %2 Hz)").arg(diff / 1000, 4).arg( 1000000.0 / diff, 4, 'f', 1) << endl;
        return false;
    }
};

int main(int argc, char **argv)
{
    QCoreApplication app(argc, argv);
    QStringList args = app.arguments();
    int rate_place = args.indexOf("-r");
    int rate_val = 0;
    if (rate_place != -1)
        rate_val = args.at(rate_place + 1).toInt();

    QMagnetometer geosensor;
    geosensor.connectToBackend();

    if (rate_val > 0) {
        geosensor.setDataRate(rate_val);
        check::checkRate(&geosensor, rate_val);
    }

    int buffer_place = args.indexOf("-b");
    int bufferSize = buffer_place!=-1? args.at(buffer_place + 1).toInt():1;
    geosensor.setProperty("bufferSize",bufferSize);

    MagGeoFilter geofilter;
    geosensor.setProperty("returnGeoValues", true);
    geosensor.addFilter(&geofilter);
    geosensor.start();
    if (!geosensor.isActive()) {
        qWarning("Magnetometersensor (geo) didn't start!");
        return 1;
    }

    QMagnetometer rawsensor;
    rawsensor.connectToBackend();
    if (rate_val > 0) {
        rawsensor.setDataRate(rate_val);
        check::checkRate(&rawsensor, rate_val);
    }
    MagRawFilter rawfilter;
    rawsensor.addFilter(&rawfilter);
    rawsensor.start();
    if (!rawsensor.isActive()) {
        qWarning("Magnetometersensor (raw) didn't start!");
        return 1;
    }
    return app.exec();
}
<|endoftext|>


<commit_before>//
// Copyright (c) 2013-2014 Christoph Malek
// See LICENSE for more information.
//

#ifndef RJ_GAME_BASIC_ENTITY_HPP
#define RJ_GAME_BASIC_ENTITY_HPP

#include "entity_base.hpp"
#include <rectojump/core/render.hpp>
#include <rectojump/global/errors.hpp>

#include <mlk/log/log.h>

namespace rj
{
	template<typename T>
	class basic_entity : public entity_base
	{
	protected:
		T m_render_object;
		vec2f m_velocity{0.f, 0.f};

		virtual void update(dur duration) override = 0;
		virtual void init() override { }

	public:
		using value_type = T;

		basic_entity(const vec2f& pos, const vec2f& velocity) :
			m_velocity{velocity}
		{m_render_object.setPosition(pos);}

		virtual ~basic_entity() = default;

		virtual void render() override
		{
			if(m_render == nullptr)
				mlk::lerr(errors::cl_nullptr_access)["rj::basic_entity<T>"];
			(*m_render)(m_render_object);
		}

		T& render_object() noexcept
		{return m_render_object;}

		// position, collision
		const vec2f& pos() const noexcept override
		{return m_render_object.getPosition();}

		float pos_x() const noexcept override
		{return this->pos().x;}

		float pos_y() const noexcept override
		{return this->pos().y;}

		virtual float top_out() const noexcept override = 0;
		virtual float bottom_out() const noexcept override = 0;
		virtual float left_out() const noexcept override = 0;
		virtual float right_out() const noexcept override = 0;
	};
}

#endif // RJ_GAME_BASIC_ENTITY_HPP
<commit_msg>basic_entity: added a const size<commit_after>//
// Copyright (c) 2013-2014 Christoph Malek
// See LICENSE for more information.
//

#ifndef RJ_GAME_BASIC_ENTITY_HPP
#define RJ_GAME_BASIC_ENTITY_HPP

#include "entity_base.hpp"
#include <rectojump/core/render.hpp>
#include <rectojump/global/errors.hpp>

#include <mlk/log/log.h>

namespace rj
{
	template<typename T>
	class basic_entity : public entity_base
	{
	protected:
		T m_render_object;
		vec2f m_velocity{0.f, 0.f};
		const vec2f m_size{48.f, 48.f};

		virtual void update(dur duration) override = 0;
		virtual void init() override { }

	public:
		using value_type = T;

		basic_entity(const vec2f& pos, const vec2f& velocity) :
			m_velocity{velocity}
		{m_render_object.setPosition(pos);}

		virtual ~basic_entity() = default;

		virtual void render() override
		{
			if(m_render == nullptr)
				mlk::lerr(errors::cl_nullptr_access)["rj::basic_entity<T>"];
			(*m_render)(m_render_object);
		}

		T& render_object() noexcept
		{return m_render_object;}

		// position, collision
		const vec2f& pos() const noexcept override
		{return m_render_object.getPosition();}

		float pos_x() const noexcept override
		{return this->pos().x;}

		float pos_y() const noexcept override
		{return this->pos().y;}

		virtual float top_out() const noexcept override = 0;
		virtual float bottom_out() const noexcept override = 0;
		virtual float left_out() const noexcept override = 0;
		virtual float right_out() const noexcept override = 0;
	};
}

#endif // RJ_GAME_BASIC_ENTITY_HPP
<|endoftext|>


<commit_before>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2015 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#ifndef MAPNIK_CVS_GRAMMAR_HPP
#define MAPNIK_CVS_GRAMMAR_HPP

//#define BOOST_SPIRIT_DEBUG

#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>

namespace mapnik {

namespace qi = boost::spirit::qi;
using csv_value  = std::string;
using csv_line = std::vector<csv_value>;
using csv_data = std::vector<csv_line>;

template <typename Iterator>
struct csv_white_space_skipper : qi::grammar<Iterator>
{
    csv_white_space_skipper()
        : csv_white_space_skipper::base_type(skip)
    {
        using namespace qi;
        qi::lit_type lit;
        skip = +lit(' ')
            ;
    }
    qi::rule<Iterator> skip;
};

template <typename Iterator, typename Skipper = csv_white_space_skipper<Iterator> >
struct csv_line_grammar : qi::grammar<Iterator, csv_line(char, char), Skipper>
{
    csv_line_grammar()
        : csv_line_grammar::base_type(line)
    {
        using namespace qi;
        qi::_a_type _a;
        qi::_r1_type _r1;
        qi::_r2_type _r2;
        qi::lit_type lit;
        qi::_1_type _1;
        qi::char_type char_;
        qi::omit_type omit;
        unesc_char.add
            ("\\a", '\a')
            ("\\b", '\b')
            ("\\f", '\f')
            ("\\n", '\n')
            ("\\r", '\r')
            ("\\t", '\t')
            ("\\v", '\v')
            ("\\\\",'\\')
            ("\\\'", '\'')
            ("\\\"", '\"')
            ("\"\"", '\"') // double quote
            ;
        line = -omit[char_("\n\r")] >> column(_r1, _r2) % lit(_r1)
            ;
        column = quoted(_r2) | *(char_ - (lit(_r1)))
            ;
        quoted = omit[char_(_r1)[_a = _1]] > text(_a) > -lit(_a) // support unmatched quotes or not (??)
            ;
        text = *(unesc_char | (char_ - lit(_r1)))
            ;
        BOOST_SPIRIT_DEBUG_NODES((line)(column)(quoted));
    }
private:
    qi::rule<Iterator, csv_line(char, char),  Skipper> line;
    qi::rule<Iterator, csv_value(char, char)> column; // no-skip
    qi::rule<Iterator, csv_value(char)> text; // no-skip
    qi::rule<Iterator, qi::locals<char>, csv_value(char)> quoted; //no-skip
    qi::symbols<char const, char const> unesc_char;
};

}

#endif // MAPNIK_CVS_GRAMMAR_HPP
<commit_msg>csv_grammar - always requre matching closing quoting character<commit_after>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2015 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#ifndef MAPNIK_CVS_GRAMMAR_HPP
#define MAPNIK_CVS_GRAMMAR_HPP

//#define BOOST_SPIRIT_DEBUG

#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>

namespace mapnik {

namespace qi = boost::spirit::qi;
using csv_value  = std::string;
using csv_line = std::vector<csv_value>;
using csv_data = std::vector<csv_line>;

template <typename Iterator>
struct csv_white_space_skipper : qi::grammar<Iterator>
{
    csv_white_space_skipper()
        : csv_white_space_skipper::base_type(skip)
    {
        using namespace qi;
        qi::lit_type lit;
        skip = +lit(' ')
            ;
    }
    qi::rule<Iterator> skip;
};

template <typename Iterator, typename Skipper = csv_white_space_skipper<Iterator> >
struct csv_line_grammar : qi::grammar<Iterator, csv_line(char, char), Skipper>
{
    csv_line_grammar()
        : csv_line_grammar::base_type(line)
    {
        using namespace qi;
        qi::_a_type _a;
        qi::_r1_type _r1;
        qi::_r2_type _r2;
        qi::lit_type lit;
        qi::_1_type _1;
        qi::char_type char_;
        qi::omit_type omit;
        unesc_char.add
            ("\\a", '\a')
            ("\\b", '\b')
            ("\\f", '\f')
            ("\\n", '\n')
            ("\\r", '\r')
            ("\\t", '\t')
            ("\\v", '\v')
            ("\\\\",'\\')
            ("\\\'", '\'')
            ("\\\"", '\"')
            ("\"\"", '\"') // double quote
            ;
        line = -omit[char_("\n\r")] >> column(_r1, _r2) % lit(_r1)
            ;
        column = quoted(_r2) | *(char_ - (lit(_r1)))
            ;
        quoted = omit[char_(_r1)[_a = _1]] > text(_a) > lit(_a) // support unmatched quotes or not (??)
            ;
        text = *(unesc_char | (char_ - lit(_r1)))
            ;
        BOOST_SPIRIT_DEBUG_NODES((line)(column)(quoted));
    }
private:
    qi::rule<Iterator, csv_line(char, char),  Skipper> line;
    qi::rule<Iterator, csv_value(char, char)> column; // no-skip
    qi::rule<Iterator, csv_value(char)> text; // no-skip
    qi::rule<Iterator, qi::locals<char>, csv_value(char)> quoted; //no-skip
    qi::symbols<char const, char const> unesc_char;
};

}

#endif // MAPNIK_CVS_GRAMMAR_HPP
<|endoftext|>


<commit_before>//============================================================================
// include/vsmc/utility/aligned_memory.hpp
//----------------------------------------------------------------------------
//
//                         vSMC: Scalable Monte Carlo
//
// This file is distributed under the 2-clauses BSD License.
// See LICENSE for details.
//============================================================================

#ifndef VSMC_UTILITY_ALIGNED_MEMORY
#define VSMC_UTILITY_ALIGNED_MEMORY

#include <vsmc/internal/common.hpp>

#if VSMC_HAS_POSIX
#include <stdlib.h>
#elif defined(_MSC_VER)
#include <malloc.h>
#endif

#if VSMC_HAS_TBB
#include <tbb/scalable_allocator.h>
#endif

#if VSMC_HAS_MKL
#include <mkl_service.h>
#endif

/// \brief Default AlignedMemory type
/// \ingroup Config
#ifndef VSMC_ALIGNED_MEMORY_TYPE
#if VSMC_HAS_POSIX || defined(_MSC_VER)
#define VSMC_ALIGNED_MEMORY_TYPE ::vsmc::AlignedMemoryNative
#elif VSMC_HAS_TBB
#define VSMC_ALIGNED_MEMORY_TYPE ::vsmc::AlignedMemoryTBB
#elif VSMC_HAS_MKL
#define VSMC_ALIGNED_MEMORY_TYPE ::vsmc::AlignedMemoryMKL
#else
#define VSMC_ALIGNED_MEMORY_TYPE ::vsmc::AlignedMemorySTD
#endif
#endif

#define VSMC_STATIC_ASSERT_UTILITY_ALIGNED_MEMORY_POWER_OF_TWO(Alignment) \
    VSMC_STATIC_ASSERT((Alignment != 0 && (Alignment & (Alignment - 1)) == 0),\
            USE_AlignedAllocator_WITH_ALIGNEMNT_NOT_A_POWER_OF_TWO)

#define VSMC_STATIC_ASSERT_UTILITY_ALIGNED_MEMORY_SIZEOF_VOID(Alignemnt) \
    VSMC_STATIC_ASSERT((Alignment >= sizeof(void *)),                        \
            USE_AlignedAllocator_WITH_ALIGNMENT_LESS_THAN_SIZEOF_VOID_POINTER)

#define VSMC_STATIC_ASSERT_UTILITY_ALIGNED_MEMORY \
    VSMC_STATIC_ASSERT_UTILITY_ALIGNED_MEMORY_POWER_OF_TWO(Alignment);    \
    VSMC_STATIC_ASSERT_UTILITY_ALIGNED_MEMORY_SIZEOF_VOID(Alignment);

#define VSMC_RUNTIME_ASSERT_UTILITY_ALIGNED_MEMORY_POWER_OF_TWO(alignment) \
    VSMC_RUNTIME_ASSERT((alignment != 0 && (alignment & (alignment - 1)) == 0),\
            "**aligned_malloc** USED WITH ALIGNMENT NOT A POWER OF TWO")

#define VSMC_RUNTIME_ASSERT_UTILITY_ALIGNED_MEMORY_SIZEOF_VOID(alignemnt) \
    VSMC_RUNTIME_ASSERT((alignment >= sizeof(void *)),                        \
            "**aligned_malloc** USED WITH ALIGNMENT LESS THAN sizeof(void *)")

#define VSMC_RUNTIME_ASSERT_UTILITY_ALIGNED_MEMORY \
    VSMC_RUNTIME_ASSERT_UTILITY_ALIGNED_MEMORY_POWER_OF_TWO(alignment);    \
    VSMC_RUNTIME_ASSERT_UTILITY_ALIGNED_MEMORY_SIZEOF_VOID(alignment);

namespace vsmc {

/// \brief Aligned memory using `std::malloc` and `std::free`
/// \ingroup AlignedMemory
///
/// \details
/// Memory allocated through this class is aligned but some bytes might be
/// wasted in each allocation.
class AlignedMemorySTD
{
    public :

    static void *aligned_malloc (std::size_t n, std::size_t alignment)
    {
        VSMC_RUNTIME_ASSERT_UTILITY_ALIGNED_MEMORY;

        if (n == 0)
            return VSMC_NULLPTR;

        void *orig_ptr = std::malloc(n + alignment + sizeof(void *));
        if (orig_ptr == VSMC_NULLPTR)
            throw std::bad_alloc();

        uintptr_t address = reinterpret_cast<uintptr_t>(orig_ptr);
        uintptr_t offset = alignment - (address + sizeof(void *)) % alignment;
        void *ptr = reinterpret_cast<void *>(address + offset + sizeof(void *));
        void **orig = reinterpret_cast<void **>(address + offset);
        *orig = orig_ptr;

        return ptr;
    }

    static void aligned_free (void *ptr)
    {
        std::free(*reinterpret_cast<void **>(
                    reinterpret_cast<uintptr_t>(ptr) - sizeof(void *)));
    }
}; // class AlignedMemmorySTD

#if VSMC_HAS_POSIX

/// \brief Aligned memory using native system aligned memory allocation
/// \ingroup AlignedMemory
///
/// \details
/// This class use `posix_memalign` and `free` on POSIX systems (Mac OS X,
/// Linux, etc.) and `_aligned_malloc` and `_aligned_free` on Windows.
class AlignedMemoryNative
{
    public :

    static void *aligned_malloc (std::size_t n, std::size_t alignment)
    {
        VSMC_RUNTIME_ASSERT_UTILITY_ALIGNED_MEMORY;

        if (n == 0)
            return VSMC_NULLPTR;

        void *ptr;
        if (posix_memalign(&ptr, alignment, n) != 0)
            throw std::bad_alloc();

        return ptr;
    }

    static void aligned_free (void *ptr) {free(ptr);}
}; // class AlignedMallocNative

#elif defined(_MSC_VER)

class AlignedMemoryNative
{
    public :

    static void *aligned_malloc (std::size_t n, std::size_t alignment)
    {
        VSMC_RUNTIME_ASSERT_UTILITY_ALIGNED_MEMORY;

        if (n == 0)
            return VSMC_NULLPTR;

        void *ptr = _aligned_malloc(n, alignment);
        if (ptr == VSMC_NULLPTR)
            throw std::bad_alloc();

        return ptr;
    }

    static void aligned_free (void *ptr) {_aligned_free(ptr);}
}; // class AlignedMemoryNative

#endif // VSMC_HAS_POSIX

#if VSMC_HAS_TBB

/// \brief Aligned memory using Intel TBB `scalable_aligned_malloc` and
/// `scalable_aligned_free`.
/// \ingroup AlignedMemory
class AlignedMemoryTBB
{
    public :

    static void *aligned_malloc (std::size_t n, std::size_t alignment)
    {
        VSMC_RUNTIME_ASSERT_UTILITY_ALIGNED_MEMORY;

        if (n == 0)
            return VSMC_NULLPTR;

        void *ptr = scalable_aligned_malloc(n, alignment);
        if (ptr == VSMC_NULLPTR)
            throw std::bad_alloc();

        return ptr;
    }

    static void aligned_free (void *ptr) {scalable_aligned_free(ptr);}
}; // class AlignedMemoryTBB

#endif // VSMC_HAS_TBB

#if VSMC_HAS_MKL

/// \brief Aligned memory using Intel MKL `mkl_malloc` and `mkl_free`
/// \ingroup AlignedMemory
class AlignedMemoryMKL
{
    public :

    static void *aligned_malloc (std::size_t n, std::size_t alignment)
    {
        VSMC_RUNTIME_ASSERT_UTILITY_ALIGNED_MEMORY;

        if (n == 0)
            return VSMC_NULLPTR;

        void *ptr = mkl_malloc(n, static_cast<int>(alignment));
        if (ptr == VSMC_NULLPTR)
            throw std::bad_alloc();

        return ptr;
    }

    static void aligned_free (void *ptr) {mkl_free(ptr);}
}; // class AlignedMemoryMKL

#endif // VSMC_HAS_MKL

/// \brief Default AlignedMemory type
/// \ingroup AlignedMemory
typedef VSMC_ALIGNED_MEMORY_TYPE AlignedMemory;

/// \brief Aligned allocator
/// \ingroup AlignedMemory
///
/// \tparam T The value type
/// \tparam Alignment The alignment requirement of memory, must be a power of
/// two and no less than `sizeof(void *)`.
/// \tparam Memory The memory management class. Must provides two member
/// functions, `aligned_malloc` and `aligned_free`. The member function
/// `aligned_malloc` shall behave similar to `std::malloc` but take an
/// additional arguments for alignment. The member function `aligned_free`
/// shall behave just like `std::free`.
template <typename T, std::size_t Alignment = 32,
         typename Memory = AlignedMemory>
class AlignedAllocator : public std::allocator<T>
{
    public :

    typedef typename std::allocator<T>::size_type size_type;
    typedef typename std::allocator<T>::pointer pointer;

    template <typename U> struct rebind
    {typedef AlignedAllocator<U, Alignment> other;};

    AlignedAllocator () {VSMC_STATIC_ASSERT_UTILITY_ALIGNED_MEMORY;}

    AlignedAllocator (const AlignedAllocator<T, Alignment> &other) :
        std::allocator<T>(other)
    {VSMC_STATIC_ASSERT_UTILITY_ALIGNED_MEMORY;}

    template <typename U>
    AlignedAllocator (const AlignedAllocator<U, Alignment> &other) :
        std::allocator<T>(static_cast<std::allocator<U> >(other))
    {VSMC_STATIC_ASSERT_UTILITY_ALIGNED_MEMORY;}

    ~AlignedAllocator () {}

    pointer allocate (size_type n, const void * = VSMC_NULLPTR)
    {
        return static_cast<pointer>(
                memory_.aligned_malloc(sizeof(T) * n, Alignment));
    }

    void deallocate (pointer ptr, size_type) {memory_.aligned_free(ptr);}

    private :

    Memory memory_;
}; // class AlignedAllocator

} // namespace vsmc

#endif // VSMC_UTILITY_ALIGNED_MEMORY
<commit_msg>clean ws<commit_after>//============================================================================
// include/vsmc/utility/aligned_memory.hpp
//----------------------------------------------------------------------------
//
//                         vSMC: Scalable Monte Carlo
//
// This file is distributed under the 2-clauses BSD License.
// See LICENSE for details.
//============================================================================

#ifndef VSMC_UTILITY_ALIGNED_MEMORY
#define VSMC_UTILITY_ALIGNED_MEMORY

#include <vsmc/internal/common.hpp>

#if VSMC_HAS_POSIX
#include <stdlib.h>
#elif defined(_MSC_VER)
#include <malloc.h>
#endif

#if VSMC_HAS_TBB
#include <tbb/scalable_allocator.h>
#endif

#if VSMC_HAS_MKL
#include <mkl_service.h>
#endif

/// \brief Default AlignedMemory type
/// \ingroup Config
#ifndef VSMC_ALIGNED_MEMORY_TYPE
#if VSMC_HAS_POSIX || defined(_MSC_VER)
#define VSMC_ALIGNED_MEMORY_TYPE ::vsmc::AlignedMemoryNative
#elif VSMC_HAS_TBB
#define VSMC_ALIGNED_MEMORY_TYPE ::vsmc::AlignedMemoryTBB
#elif VSMC_HAS_MKL
#define VSMC_ALIGNED_MEMORY_TYPE ::vsmc::AlignedMemoryMKL
#else
#define VSMC_ALIGNED_MEMORY_TYPE ::vsmc::AlignedMemorySTD
#endif
#endif

#define VSMC_STATIC_ASSERT_UTILITY_ALIGNED_MEMORY_POWER_OF_TWO(Alignment) \
    VSMC_STATIC_ASSERT((Alignment != 0 && (Alignment & (Alignment - 1)) == 0),\
            USE_AlignedAllocator_WITH_ALIGNEMNT_NOT_A_POWER_OF_TWO)

#define VSMC_STATIC_ASSERT_UTILITY_ALIGNED_MEMORY_SIZEOF_VOID(Alignemnt) \
    VSMC_STATIC_ASSERT((Alignment >= sizeof(void *)),                        \
            USE_AlignedAllocator_WITH_ALIGNMENT_LESS_THAN_SIZEOF_VOID_POINTER)

#define VSMC_STATIC_ASSERT_UTILITY_ALIGNED_MEMORY \
    VSMC_STATIC_ASSERT_UTILITY_ALIGNED_MEMORY_POWER_OF_TWO(Alignment);    \
    VSMC_STATIC_ASSERT_UTILITY_ALIGNED_MEMORY_SIZEOF_VOID(Alignment);

#define VSMC_RUNTIME_ASSERT_UTILITY_ALIGNED_MEMORY_POWER_OF_TWO(alignment) \
    VSMC_RUNTIME_ASSERT((alignment != 0 && (alignment & (alignment - 1)) == 0),\
            "**aligned_malloc** USED WITH ALIGNMENT NOT A POWER OF TWO")

#define VSMC_RUNTIME_ASSERT_UTILITY_ALIGNED_MEMORY_SIZEOF_VOID(alignemnt) \
    VSMC_RUNTIME_ASSERT((alignment >= sizeof(void *)),                        \
            "**aligned_malloc** USED WITH ALIGNMENT LESS THAN sizeof(void *)")

#define VSMC_RUNTIME_ASSERT_UTILITY_ALIGNED_MEMORY \
    VSMC_RUNTIME_ASSERT_UTILITY_ALIGNED_MEMORY_POWER_OF_TWO(alignment);    \
    VSMC_RUNTIME_ASSERT_UTILITY_ALIGNED_MEMORY_SIZEOF_VOID(alignment);

namespace vsmc {

/// \brief Aligned memory using `std::malloc` and `std::free`
/// \ingroup AlignedMemory
///
/// \details
/// Memory allocated through this class is aligned but some bytes might be
/// wasted in each allocation.
class AlignedMemorySTD
{
    public :

    static void *aligned_malloc (std::size_t n, std::size_t alignment)
    {
        VSMC_RUNTIME_ASSERT_UTILITY_ALIGNED_MEMORY;

        if (n == 0)
            return VSMC_NULLPTR;

        void *orig_ptr = std::malloc(n + alignment + sizeof(void *));
        if (orig_ptr == VSMC_NULLPTR)
            throw std::bad_alloc();

        uintptr_t address = reinterpret_cast<uintptr_t>(orig_ptr);
        uintptr_t offset = alignment - (address + sizeof(void *)) % alignment;
        void *ptr = reinterpret_cast<void *>(address + offset + sizeof(void *));
        void **orig = reinterpret_cast<void **>(address + offset);
        *orig = orig_ptr;

        return ptr;
    }

    static void aligned_free (void *ptr)
    {
        std::free(*reinterpret_cast<void **>(
                    reinterpret_cast<uintptr_t>(ptr) - sizeof(void *)));
    }
}; // class AlignedMemmorySTD

#if VSMC_HAS_POSIX

/// \brief Aligned memory using native system aligned memory allocation
/// \ingroup AlignedMemory
///
/// \details
/// This class use `posix_memalign` and `free` on POSIX systems (Mac OS X,
/// Linux, etc.) and `_aligned_malloc` and `_aligned_free` on Windows.
class AlignedMemoryNative
{
    public :

    static void *aligned_malloc (std::size_t n, std::size_t alignment)
    {
        VSMC_RUNTIME_ASSERT_UTILITY_ALIGNED_MEMORY;

        if (n == 0)
            return VSMC_NULLPTR;

        void *ptr;
        if (posix_memalign(&ptr, alignment, n) != 0)
            throw std::bad_alloc();

        return ptr;
    }

    static void aligned_free (void *ptr) {free(ptr);}
}; // class AlignedMallocNative

#elif defined(_MSC_VER)

class AlignedMemoryNative
{
    public :

    static void *aligned_malloc (std::size_t n, std::size_t alignment)
    {
        VSMC_RUNTIME_ASSERT_UTILITY_ALIGNED_MEMORY;

        if (n == 0)
            return VSMC_NULLPTR;

        void *ptr = _aligned_malloc(n, alignment);
        if (ptr == VSMC_NULLPTR)
            throw std::bad_alloc();

        return ptr;
    }

    static void aligned_free (void *ptr) {_aligned_free(ptr);}
}; // class AlignedMemoryNative

#endif // VSMC_HAS_POSIX

#if VSMC_HAS_TBB

/// \brief Aligned memory using Intel TBB `scalable_aligned_malloc` and
/// `scalable_aligned_free`.
/// \ingroup AlignedMemory
class AlignedMemoryTBB
{
    public :

    static void *aligned_malloc (std::size_t n, std::size_t alignment)
    {
        VSMC_RUNTIME_ASSERT_UTILITY_ALIGNED_MEMORY;

        if (n == 0)
            return VSMC_NULLPTR;

        void *ptr = scalable_aligned_malloc(n, alignment);
        if (ptr == VSMC_NULLPTR)
            throw std::bad_alloc();

        return ptr;
    }

    static void aligned_free (void *ptr) {scalable_aligned_free(ptr);}
}; // class AlignedMemoryTBB

#endif // VSMC_HAS_TBB

#if VSMC_HAS_MKL

/// \brief Aligned memory using Intel MKL `mkl_malloc` and `mkl_free`
/// \ingroup AlignedMemory
class AlignedMemoryMKL
{
    public :

    static void *aligned_malloc (std::size_t n, std::size_t alignment)
    {
        VSMC_RUNTIME_ASSERT_UTILITY_ALIGNED_MEMORY;

        if (n == 0)
            return VSMC_NULLPTR;

        void *ptr = mkl_malloc(n, static_cast<int>(alignment));
        if (ptr == VSMC_NULLPTR)
            throw std::bad_alloc();

        return ptr;
    }

    static void aligned_free (void *ptr) {mkl_free(ptr);}
}; // class AlignedMemoryMKL

#endif // VSMC_HAS_MKL

/// \brief Default AlignedMemory type
/// \ingroup AlignedMemory
typedef VSMC_ALIGNED_MEMORY_TYPE AlignedMemory;

/// \brief Aligned allocator
/// \ingroup AlignedMemory
///
/// \tparam T The value type
/// \tparam Alignment The alignment requirement of memory, must be a power of
/// two and no less than `sizeof(void *)`.
/// \tparam Memory The memory management class. Must provides two member
/// functions, `aligned_malloc` and `aligned_free`. The member function
/// `aligned_malloc` shall behave similar to `std::malloc` but take an
/// additional arguments for alignment. The member function `aligned_free`
/// shall behave just like `std::free`.
template <typename T, std::size_t Alignment = 32,
         typename Memory = AlignedMemory>
class AlignedAllocator : public std::allocator<T>
{
    public :

    typedef typename std::allocator<T>::size_type size_type;
    typedef typename std::allocator<T>::pointer pointer;

    template <typename U> struct rebind
    {typedef AlignedAllocator<U, Alignment> other;};

    AlignedAllocator () {VSMC_STATIC_ASSERT_UTILITY_ALIGNED_MEMORY;}

    AlignedAllocator (const AlignedAllocator<T, Alignment> &other) :
        std::allocator<T>(other)
    {VSMC_STATIC_ASSERT_UTILITY_ALIGNED_MEMORY;}

    template <typename U>
    AlignedAllocator (const AlignedAllocator<U, Alignment> &other) :
        std::allocator<T>(static_cast<std::allocator<U> >(other))
    {VSMC_STATIC_ASSERT_UTILITY_ALIGNED_MEMORY;}

    ~AlignedAllocator () {}

    pointer allocate (size_type n, const void * = VSMC_NULLPTR)
    {
        return static_cast<pointer>(
                memory_.aligned_malloc(sizeof(T) * n, Alignment));
    }

    void deallocate (pointer ptr, size_type) {memory_.aligned_free(ptr);}

    private :

    Memory memory_;
}; // class AlignedAllocator

} // namespace vsmc

#endif // VSMC_UTILITY_ALIGNED_MEMORY
<|endoftext|>


<commit_before>/*
 *  Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "media/engine/videoencodersoftwarefallbackwrapper.h"

#include <utility>

#include "media/base/h264_profile_level_id.h"
#include "media/engine/internalencoderfactory.h"
#include "modules/video_coding/include/video_error_codes.h"
#include "rtc_base/checks.h"
#include "rtc_base/logging.h"
#include "rtc_base/timeutils.h"
#include "system_wrappers/include/field_trial.h"

namespace webrtc {
namespace {
const char kVp8ForceFallbackEncoderFieldTrial[] =
    "WebRTC-VP8-Forced-Fallback-Encoder-v2";

bool EnableForcedFallback() {
  return field_trial::IsEnabled(kVp8ForceFallbackEncoderFieldTrial);
}

bool IsForcedFallbackPossible(const VideoCodec& codec_settings) {
  return codec_settings.codecType == kVideoCodecVP8 &&
         codec_settings.numberOfSimulcastStreams <= 1 &&
         codec_settings.VP8().numberOfTemporalLayers == 1;
}

void GetForcedFallbackParamsFromFieldTrialGroup(int* param_min_pixels,
                                                int* param_max_pixels,
                                                int minimum_max_pixels) {
  RTC_DCHECK(param_min_pixels);
  RTC_DCHECK(param_max_pixels);
  std::string group =
      webrtc::field_trial::FindFullName(kVp8ForceFallbackEncoderFieldTrial);
  if (group.empty())
    return;

  int min_pixels;
  int max_pixels;
  int min_bps;
  if (sscanf(group.c_str(), "Enabled-%d,%d,%d", &min_pixels, &max_pixels,
             &min_bps) != 3) {
    RTC_LOG(LS_WARNING)
        << "Invalid number of forced fallback parameters provided.";
    return;
  }
  if (min_pixels <= 0 || max_pixels < minimum_max_pixels ||
      max_pixels < min_pixels || min_bps <= 0) {
    RTC_LOG(LS_WARNING) << "Invalid forced fallback parameter value provided.";
    return;
  }
  *param_min_pixels = min_pixels;
  *param_max_pixels = max_pixels;
}
}  // namespace

VideoEncoderSoftwareFallbackWrapper::VideoEncoderSoftwareFallbackWrapper(
    std::unique_ptr<webrtc::VideoEncoder> sw_encoder,
    std::unique_ptr<webrtc::VideoEncoder> hw_encoder)
    : number_of_cores_(0),
      max_payload_size_(0),
      rates_set_(false),
      framerate_(0),
      channel_parameters_set_(false),
      packet_loss_(0),
      rtt_(0),
      use_fallback_encoder_(false),
      encoder_(std::move(hw_encoder)),
      fallback_encoder_(std::move(sw_encoder)),
      callback_(nullptr),
      forced_fallback_possible_(EnableForcedFallback()) {
  if (forced_fallback_possible_) {
    GetForcedFallbackParamsFromFieldTrialGroup(
        &forced_fallback_.min_pixels_, &forced_fallback_.max_pixels_,
        encoder_->GetScalingSettings().min_pixels_per_frame -
            1);  // No HW below.
  }
}

bool VideoEncoderSoftwareFallbackWrapper::InitFallbackEncoder() {
  RTC_LOG(LS_WARNING) << "Encoder falling back to software encoding.";

  const int ret = fallback_encoder_->InitEncode(
      &codec_settings_, number_of_cores_, max_payload_size_);
  use_fallback_encoder_ = (ret == WEBRTC_VIDEO_CODEC_OK);
  if (!use_fallback_encoder_) {
    RTC_LOG(LS_ERROR) << "Failed to initialize software-encoder fallback.";
    fallback_encoder_->Release();
    return false;
  }
  // Replay callback, rates, and channel parameters.
  if (callback_)
    fallback_encoder_->RegisterEncodeCompleteCallback(callback_);
  if (rates_set_)
    fallback_encoder_->SetRateAllocation(bitrate_allocation_, framerate_);
  if (channel_parameters_set_)
    fallback_encoder_->SetChannelParameters(packet_loss_, rtt_);

  // Since we're switching to the fallback encoder, Release the real encoder. It
  // may be re-initialized via InitEncode later, and it will continue to get
  // Set calls for rates and channel parameters in the meantime.
  encoder_->Release();
  return true;
}

int32_t VideoEncoderSoftwareFallbackWrapper::InitEncode(
    const VideoCodec* codec_settings,
    int32_t number_of_cores,
    size_t max_payload_size) {
  // Store settings, in case we need to dynamically switch to the fallback
  // encoder after a failed Encode call.
  codec_settings_ = *codec_settings;
  number_of_cores_ = number_of_cores;
  max_payload_size_ = max_payload_size;
  // Clear stored rate/channel parameters.
  rates_set_ = false;
  channel_parameters_set_ = false;
  ValidateSettingsForForcedFallback();

  // Try to reinit forced software codec if it is in use.
  if (TryReInitForcedFallbackEncoder()) {
    return WEBRTC_VIDEO_CODEC_OK;
  }
  // Try to init forced software codec if it should be used.
  if (TryInitForcedFallbackEncoder()) {
    return WEBRTC_VIDEO_CODEC_OK;
  }
  forced_fallback_.active_ = false;

  int32_t ret =
      encoder_->InitEncode(codec_settings, number_of_cores, max_payload_size);
  if (ret == WEBRTC_VIDEO_CODEC_OK) {
    if (use_fallback_encoder_) {
      RTC_LOG(LS_WARNING)
          << "InitEncode OK, no longer using the software fallback encoder.";
      fallback_encoder_->Release();
      use_fallback_encoder_ = false;
    }
    if (callback_)
      encoder_->RegisterEncodeCompleteCallback(callback_);
    return ret;
  }
  // Try to instantiate software codec.
  if (InitFallbackEncoder()) {
    return WEBRTC_VIDEO_CODEC_OK;
  }
  // Software encoder failed, use original return code.
  return ret;
}

int32_t VideoEncoderSoftwareFallbackWrapper::RegisterEncodeCompleteCallback(
    EncodedImageCallback* callback) {
  callback_ = callback;
  int32_t ret = encoder_->RegisterEncodeCompleteCallback(callback);
  if (use_fallback_encoder_)
    return fallback_encoder_->RegisterEncodeCompleteCallback(callback);
  return ret;
}

int32_t VideoEncoderSoftwareFallbackWrapper::Release() {
  return use_fallback_encoder_ ? fallback_encoder_->Release()
                               : encoder_->Release();
}

int32_t VideoEncoderSoftwareFallbackWrapper::Encode(
    const VideoFrame& frame,
    const CodecSpecificInfo* codec_specific_info,
    const std::vector<FrameType>* frame_types) {
  if (use_fallback_encoder_)
    return fallback_encoder_->Encode(frame, codec_specific_info, frame_types);
  int32_t ret = encoder_->Encode(frame, codec_specific_info, frame_types);
  // If requested, try a software fallback.
  bool fallback_requested = (ret == WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE);
  if (fallback_requested && InitFallbackEncoder()) {
    if (frame.video_frame_buffer()->type() == VideoFrameBuffer::Type::kNative &&
        !fallback_encoder_->SupportsNativeHandle()) {
      RTC_LOG(LS_WARNING) << "Fallback encoder doesn't support native frames, "
                          << "dropping one frame.";
      return WEBRTC_VIDEO_CODEC_ERROR;
    }

    // Start using the fallback with this frame.
    return fallback_encoder_->Encode(frame, codec_specific_info, frame_types);
  }
  return ret;
}

int32_t VideoEncoderSoftwareFallbackWrapper::SetChannelParameters(
    uint32_t packet_loss,
    int64_t rtt) {
  channel_parameters_set_ = true;
  packet_loss_ = packet_loss;
  rtt_ = rtt;
  int32_t ret = encoder_->SetChannelParameters(packet_loss, rtt);
  if (use_fallback_encoder_)
    return fallback_encoder_->SetChannelParameters(packet_loss, rtt);
  return ret;
}

int32_t VideoEncoderSoftwareFallbackWrapper::SetRateAllocation(
    const BitrateAllocation& bitrate_allocation,
    uint32_t framerate) {
  rates_set_ = true;
  bitrate_allocation_ = bitrate_allocation;
  framerate_ = framerate;
  int32_t ret = encoder_->SetRateAllocation(bitrate_allocation_, framerate);
  if (use_fallback_encoder_)
    return fallback_encoder_->SetRateAllocation(bitrate_allocation_, framerate);
  return ret;
}

bool VideoEncoderSoftwareFallbackWrapper::SupportsNativeHandle() const {
  return use_fallback_encoder_ ? fallback_encoder_->SupportsNativeHandle()
                               : encoder_->SupportsNativeHandle();
}

VideoEncoder::ScalingSettings
VideoEncoderSoftwareFallbackWrapper::GetScalingSettings() const {
  if (forced_fallback_possible_) {
    if (forced_fallback_.active_) {
      return VideoEncoder::ScalingSettings(
          codec_settings_.VP8().automaticResizeOn,
          forced_fallback_.min_pixels_);
    }
    const auto settings = encoder_->GetScalingSettings();
    if (settings.thresholds) {
      return VideoEncoder::ScalingSettings(
          settings.enabled, settings.thresholds->low, settings.thresholds->high,
          forced_fallback_.min_pixels_);
    }
    return VideoEncoder::ScalingSettings(settings.enabled,
                                         forced_fallback_.min_pixels_);
  }
  return encoder_->GetScalingSettings();
}

const char* VideoEncoderSoftwareFallbackWrapper::ImplementationName() const {
  return use_fallback_encoder_ ? fallback_encoder_->ImplementationName()
                               : encoder_->ImplementationName();
}

bool VideoEncoderSoftwareFallbackWrapper::IsForcedFallbackActive() const {
  return (forced_fallback_possible_ && use_fallback_encoder_ &&
          forced_fallback_.active_);
}

bool VideoEncoderSoftwareFallbackWrapper::TryInitForcedFallbackEncoder() {
  if (!forced_fallback_possible_ || use_fallback_encoder_) {
    return false;
  }
  // Fallback not active.
  if (!forced_fallback_.IsValid(codec_settings_)) {
    return false;
  }
  // Settings valid, try to instantiate software codec.
  RTC_LOG(LS_INFO) << "Request forced SW encoder fallback: "
                   << codec_settings_.width << "x" << codec_settings_.height;
  if (!InitFallbackEncoder()) {
    return false;
  }
  forced_fallback_.active_ = true;
  return true;
}

bool VideoEncoderSoftwareFallbackWrapper::TryReInitForcedFallbackEncoder() {
  if (!IsForcedFallbackActive()) {
    return false;
  }
  // Forced fallback active.
  if (!forced_fallback_.IsValid(codec_settings_)) {
    RTC_LOG(LS_INFO) << "Stop forced SW encoder fallback, max pixels exceeded.";
    return false;
  }
  // Settings valid, reinitialize the forced fallback encoder.
  if (fallback_encoder_->InitEncode(&codec_settings_, number_of_cores_,
                                    max_payload_size_) !=
      WEBRTC_VIDEO_CODEC_OK) {
    RTC_LOG(LS_ERROR) << "Failed to init forced SW encoder fallback.";
    return false;
  }
  return true;
}

void VideoEncoderSoftwareFallbackWrapper::ValidateSettingsForForcedFallback() {
  if (!forced_fallback_possible_)
    return;

  if (!IsForcedFallbackPossible(codec_settings_)) {
    if (IsForcedFallbackActive()) {
      fallback_encoder_->Release();
      use_fallback_encoder_ = false;
    }
    RTC_LOG(LS_INFO) << "Disable forced_fallback_possible_ due to settings.";
    forced_fallback_possible_ = false;
  }
}

}  // namespace webrtc
<commit_msg>Allow first frame after fallback in VideoEncoderSoftwareFallbackWrapper<commit_after>/*
 *  Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "media/engine/videoencodersoftwarefallbackwrapper.h"

#include <utility>

#include "media/base/h264_profile_level_id.h"
#include "media/engine/internalencoderfactory.h"
#include "modules/video_coding/include/video_error_codes.h"
#include "rtc_base/checks.h"
#include "rtc_base/logging.h"
#include "rtc_base/timeutils.h"
#include "system_wrappers/include/field_trial.h"

namespace webrtc {
namespace {
const char kVp8ForceFallbackEncoderFieldTrial[] =
    "WebRTC-VP8-Forced-Fallback-Encoder-v2";

bool EnableForcedFallback() {
  return field_trial::IsEnabled(kVp8ForceFallbackEncoderFieldTrial);
}

bool IsForcedFallbackPossible(const VideoCodec& codec_settings) {
  return codec_settings.codecType == kVideoCodecVP8 &&
         codec_settings.numberOfSimulcastStreams <= 1 &&
         codec_settings.VP8().numberOfTemporalLayers == 1;
}

void GetForcedFallbackParamsFromFieldTrialGroup(int* param_min_pixels,
                                                int* param_max_pixels,
                                                int minimum_max_pixels) {
  RTC_DCHECK(param_min_pixels);
  RTC_DCHECK(param_max_pixels);
  std::string group =
      webrtc::field_trial::FindFullName(kVp8ForceFallbackEncoderFieldTrial);
  if (group.empty())
    return;

  int min_pixels;
  int max_pixels;
  int min_bps;
  if (sscanf(group.c_str(), "Enabled-%d,%d,%d", &min_pixels, &max_pixels,
             &min_bps) != 3) {
    RTC_LOG(LS_WARNING)
        << "Invalid number of forced fallback parameters provided.";
    return;
  }
  if (min_pixels <= 0 || max_pixels < minimum_max_pixels ||
      max_pixels < min_pixels || min_bps <= 0) {
    RTC_LOG(LS_WARNING) << "Invalid forced fallback parameter value provided.";
    return;
  }
  *param_min_pixels = min_pixels;
  *param_max_pixels = max_pixels;
}
}  // namespace

VideoEncoderSoftwareFallbackWrapper::VideoEncoderSoftwareFallbackWrapper(
    std::unique_ptr<webrtc::VideoEncoder> sw_encoder,
    std::unique_ptr<webrtc::VideoEncoder> hw_encoder)
    : number_of_cores_(0),
      max_payload_size_(0),
      rates_set_(false),
      framerate_(0),
      channel_parameters_set_(false),
      packet_loss_(0),
      rtt_(0),
      use_fallback_encoder_(false),
      encoder_(std::move(hw_encoder)),
      fallback_encoder_(std::move(sw_encoder)),
      callback_(nullptr),
      forced_fallback_possible_(EnableForcedFallback()) {
  if (forced_fallback_possible_) {
    GetForcedFallbackParamsFromFieldTrialGroup(
        &forced_fallback_.min_pixels_, &forced_fallback_.max_pixels_,
        encoder_->GetScalingSettings().min_pixels_per_frame -
            1);  // No HW below.
  }
}

bool VideoEncoderSoftwareFallbackWrapper::InitFallbackEncoder() {
  RTC_LOG(LS_WARNING) << "Encoder falling back to software encoding.";

  const int ret = fallback_encoder_->InitEncode(
      &codec_settings_, number_of_cores_, max_payload_size_);
  use_fallback_encoder_ = (ret == WEBRTC_VIDEO_CODEC_OK);
  if (!use_fallback_encoder_) {
    RTC_LOG(LS_ERROR) << "Failed to initialize software-encoder fallback.";
    fallback_encoder_->Release();
    return false;
  }
  // Replay callback, rates, and channel parameters.
  if (callback_)
    fallback_encoder_->RegisterEncodeCompleteCallback(callback_);
  if (rates_set_)
    fallback_encoder_->SetRateAllocation(bitrate_allocation_, framerate_);
  if (channel_parameters_set_)
    fallback_encoder_->SetChannelParameters(packet_loss_, rtt_);

  // Since we're switching to the fallback encoder, Release the real encoder. It
  // may be re-initialized via InitEncode later, and it will continue to get
  // Set calls for rates and channel parameters in the meantime.
  encoder_->Release();
  return true;
}

int32_t VideoEncoderSoftwareFallbackWrapper::InitEncode(
    const VideoCodec* codec_settings,
    int32_t number_of_cores,
    size_t max_payload_size) {
  // Store settings, in case we need to dynamically switch to the fallback
  // encoder after a failed Encode call.
  codec_settings_ = *codec_settings;
  number_of_cores_ = number_of_cores;
  max_payload_size_ = max_payload_size;
  // Clear stored rate/channel parameters.
  rates_set_ = false;
  channel_parameters_set_ = false;
  ValidateSettingsForForcedFallback();

  // Try to reinit forced software codec if it is in use.
  if (TryReInitForcedFallbackEncoder()) {
    return WEBRTC_VIDEO_CODEC_OK;
  }
  // Try to init forced software codec if it should be used.
  if (TryInitForcedFallbackEncoder()) {
    return WEBRTC_VIDEO_CODEC_OK;
  }
  forced_fallback_.active_ = false;

  int32_t ret =
      encoder_->InitEncode(codec_settings, number_of_cores, max_payload_size);
  if (ret == WEBRTC_VIDEO_CODEC_OK) {
    if (use_fallback_encoder_) {
      RTC_LOG(LS_WARNING)
          << "InitEncode OK, no longer using the software fallback encoder.";
      fallback_encoder_->Release();
      use_fallback_encoder_ = false;
    }
    if (callback_)
      encoder_->RegisterEncodeCompleteCallback(callback_);
    return ret;
  }
  // Try to instantiate software codec.
  if (InitFallbackEncoder()) {
    return WEBRTC_VIDEO_CODEC_OK;
  }
  // Software encoder failed, use original return code.
  return ret;
}

int32_t VideoEncoderSoftwareFallbackWrapper::RegisterEncodeCompleteCallback(
    EncodedImageCallback* callback) {
  callback_ = callback;
  int32_t ret = encoder_->RegisterEncodeCompleteCallback(callback);
  if (use_fallback_encoder_)
    return fallback_encoder_->RegisterEncodeCompleteCallback(callback);
  return ret;
}

int32_t VideoEncoderSoftwareFallbackWrapper::Release() {
  return use_fallback_encoder_ ? fallback_encoder_->Release()
                               : encoder_->Release();
}

int32_t VideoEncoderSoftwareFallbackWrapper::Encode(
    const VideoFrame& frame,
    const CodecSpecificInfo* codec_specific_info,
    const std::vector<FrameType>* frame_types) {
  if (use_fallback_encoder_)
    return fallback_encoder_->Encode(frame, codec_specific_info, frame_types);
  int32_t ret = encoder_->Encode(frame, codec_specific_info, frame_types);
  // If requested, try a software fallback.
  bool fallback_requested = (ret == WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE);
  if (fallback_requested && InitFallbackEncoder()) {
    // Start using the fallback with this frame.
    return fallback_encoder_->Encode(frame, codec_specific_info, frame_types);
  }
  return ret;
}

int32_t VideoEncoderSoftwareFallbackWrapper::SetChannelParameters(
    uint32_t packet_loss,
    int64_t rtt) {
  channel_parameters_set_ = true;
  packet_loss_ = packet_loss;
  rtt_ = rtt;
  int32_t ret = encoder_->SetChannelParameters(packet_loss, rtt);
  if (use_fallback_encoder_)
    return fallback_encoder_->SetChannelParameters(packet_loss, rtt);
  return ret;
}

int32_t VideoEncoderSoftwareFallbackWrapper::SetRateAllocation(
    const BitrateAllocation& bitrate_allocation,
    uint32_t framerate) {
  rates_set_ = true;
  bitrate_allocation_ = bitrate_allocation;
  framerate_ = framerate;
  int32_t ret = encoder_->SetRateAllocation(bitrate_allocation_, framerate);
  if (use_fallback_encoder_)
    return fallback_encoder_->SetRateAllocation(bitrate_allocation_, framerate);
  return ret;
}

bool VideoEncoderSoftwareFallbackWrapper::SupportsNativeHandle() const {
  return use_fallback_encoder_ ? fallback_encoder_->SupportsNativeHandle()
                               : encoder_->SupportsNativeHandle();
}

VideoEncoder::ScalingSettings
VideoEncoderSoftwareFallbackWrapper::GetScalingSettings() const {
  if (forced_fallback_possible_) {
    if (forced_fallback_.active_) {
      return VideoEncoder::ScalingSettings(
          codec_settings_.VP8().automaticResizeOn,
          forced_fallback_.min_pixels_);
    }
    const auto settings = encoder_->GetScalingSettings();
    if (settings.thresholds) {
      return VideoEncoder::ScalingSettings(
          settings.enabled, settings.thresholds->low, settings.thresholds->high,
          forced_fallback_.min_pixels_);
    }
    return VideoEncoder::ScalingSettings(settings.enabled,
                                         forced_fallback_.min_pixels_);
  }
  return encoder_->GetScalingSettings();
}

const char* VideoEncoderSoftwareFallbackWrapper::ImplementationName() const {
  return use_fallback_encoder_ ? fallback_encoder_->ImplementationName()
                               : encoder_->ImplementationName();
}

bool VideoEncoderSoftwareFallbackWrapper::IsForcedFallbackActive() const {
  return (forced_fallback_possible_ && use_fallback_encoder_ &&
          forced_fallback_.active_);
}

bool VideoEncoderSoftwareFallbackWrapper::TryInitForcedFallbackEncoder() {
  if (!forced_fallback_possible_ || use_fallback_encoder_) {
    return false;
  }
  // Fallback not active.
  if (!forced_fallback_.IsValid(codec_settings_)) {
    return false;
  }
  // Settings valid, try to instantiate software codec.
  RTC_LOG(LS_INFO) << "Request forced SW encoder fallback: "
                   << codec_settings_.width << "x" << codec_settings_.height;
  if (!InitFallbackEncoder()) {
    return false;
  }
  forced_fallback_.active_ = true;
  return true;
}

bool VideoEncoderSoftwareFallbackWrapper::TryReInitForcedFallbackEncoder() {
  if (!IsForcedFallbackActive()) {
    return false;
  }
  // Forced fallback active.
  if (!forced_fallback_.IsValid(codec_settings_)) {
    RTC_LOG(LS_INFO) << "Stop forced SW encoder fallback, max pixels exceeded.";
    return false;
  }
  // Settings valid, reinitialize the forced fallback encoder.
  if (fallback_encoder_->InitEncode(&codec_settings_, number_of_cores_,
                                    max_payload_size_) !=
      WEBRTC_VIDEO_CODEC_OK) {
    RTC_LOG(LS_ERROR) << "Failed to init forced SW encoder fallback.";
    return false;
  }
  return true;
}

void VideoEncoderSoftwareFallbackWrapper::ValidateSettingsForForcedFallback() {
  if (!forced_fallback_possible_)
    return;

  if (!IsForcedFallbackPossible(codec_settings_)) {
    if (IsForcedFallbackActive()) {
      fallback_encoder_->Release();
      use_fallback_encoder_ = false;
    }
    RTC_LOG(LS_INFO) << "Disable forced_fallback_possible_ due to settings.";
    forced_fallback_possible_ = false;
  }
}

}  // namespace webrtc
<|endoftext|>


<commit_before>#ifndef VSMC_UTILITY_OPENCL_MANAGER_HPP
#define VSMC_UTILITY_OPENCL_MANAGER_HPP

#define __CL_ENABLE_EXCEPTIONS

#include <vsmc/internal/common.hpp>
#include <vsmc/utility/opencl/cl_wrapper.hpp>

namespace vsmc { namespace opencl {

struct Default
{
    typedef cxx11::integral_constant<cl_device_type, CL_DEVICE_TYPE_DEFAULT>
        opencl_device_type;
};

struct All
{
    typedef cxx11::integral_constant<cl_device_type, CL_DEVICE_TYPE_ALL>
        opencl_device_type;
};

struct CPU
{
    typedef cxx11::integral_constant<cl_device_type, CL_DEVICE_TYPE_CPU>
        opencl_device_type;
};

struct GPU
{
    typedef cxx11::integral_constant<cl_device_type, CL_DEVICE_TYPE_GPU>
        opencl_device_type;
};

struct Accelerator
{
    typedef cxx11::integral_constant<cl_device_type,
        CL_DEVICE_TYPE_ACCELERATOR> opencl_device_type;
};

struct Apple
{
    static bool check_opencl_platform (const std::string &name)
    {return name == std::string("Apple");}
};

struct Intel
{
    static bool check_opencl_platform (const std::string &name)
    {return name == std::string("Intel(R) OpenCL");}
};

struct AMD
{
    static bool check_opencl_platform (const std::string &name)
    {return name == std::string("AMD");}
};

struct NVIDIA
{
    static bool check_opencl_platform (const std::string &name)
    {return name == std::string("NVIDIA");}
};

struct AppleCPU : public Apple, public CPU {};
struct AppleGPU : public Apple, public GPU {};

struct IntelCPU : public Intel, public CPU {};
struct IntelGPU : public Intel, public GPU {};

struct AMDCPU : public AMD, public CPU {};
struct AMDGPU : public AMD, public GPU {};

struct NVIDIACPU : public NVIDIA, public CPU {};
struct NVIDIAGPU : public NVIDIA, public GPU {};

class LocalSize
{
    public :

    LocalSize () : local_size_(0) {}

    std::size_t local_size () const
    {
        return local_size_;
    }

    void local_size (std::size_t new_size)
    {
        local_size_ = new_size;
    }

    static std::size_t preferred_local_size (
            const cl::Kernel &kern, const cl::Device &dev)
    {
        std::size_t max_s;
        std::size_t mul_s;
        kern.getWorkGroupInfo(dev, CL_KERNEL_WORK_GROUP_SIZE, &max_s);
        kern.getWorkGroupInfo(dev,
                CL_KERNEL_PREFERRED_WORK_GROUP_SIZE_MULTIPLE, &mul_s);

        return (max_s / mul_s) * mul_s;
    }

    private :

    std::size_t local_size_;
}; // class LocalSize

/// \brief OpenCL Manager
/// \ingroup OpenCL
template <typename ID>
class CLManager
{
    public :

    typedef std::size_t size_type;

    static CLManager<ID> &instance ()
    {
        static CLManager<ID> manager;

        return manager;
    }

    const cl::Platform &platform () const
    {
        return platform_;
    }

    const std::vector<cl::Platform> &platform_vec () const
    {
        return platform_vec_;
    }

    const cl::Context &context () const
    {
        return context_;
    }

    const cl::Device &device () const
    {
        return device_;
    }

    const std::vector<cl::Device> &device_vec () const
    {
        return device_vec_;
    }

    const cl::CommandQueue &command_queue () const
    {
        return command_queue_;
    }

    bool setup () const
    {
        return setup_;
    }

    void setup (cl_device_type dev)
    {
        setup_ = false;
        setup_cl_manager(dev);
    }

    void setup (const cl::Platform &plat, const cl::Context &ctx,
            const cl::Device &dev, const cl::CommandQueue &cmd)
    {
        setup_ = false;
        platform_ = plat;
        cl::Platform::get(&platform_vec_);
        context_ = ctx;
        device_ = dev;
        device_vec_ = context_.getInfo<CL_CONTEXT_DEVICES>();
        command_queue_ = cmd;
        setup_ = true;
    }

    template<typename CLType>
    cl::Buffer create_buffer (size_type num) const
    {
        VSMC_RUNTIME_ASSERT_CL_MANAGER_SETUP(create_buffer);
        VSMC_RUNTIME_ASSERT((num),
                "CALL vsmc::CLManager::crate_buffer WITH ZERO SIZE");

        if (!num)
            return cl::Buffer();

        return cl::Buffer(context_, CL_MEM_READ_WRITE, sizeof(CLType) * num);
    }

    template<typename CLType, typename InputIter>
    cl::Buffer create_buffer (InputIter first, InputIter last) const
    {
        VSMC_RUNTIME_ASSERT_CL_MANAGER_SETUP(create_buffer);

        size_type num = 0;
        for (InputIter i = first; i != last; ++i)
            ++num;

        if (!num)
            return cl::Buffer();

        cl::Buffer buf(create_buffer<CLType>(num));
        write_buffer<CLType>(buf, num, first);

        return buf;
    }

    template <typename CLType, typename OutputIter>
    OutputIter read_buffer (const cl::Buffer &buf, size_type num,
            OutputIter first) const
    {
        VSMC_RUNTIME_ASSERT_CL_MANAGER_SETUP(read_buffer);

        CLType *temp = read_buffer_pool<CLType>(num);
        command_queue_.finish();
        command_queue_.enqueueReadBuffer(buf, 1, 0, sizeof(CLType) * num,
                (void *) temp);

        return std::copy(temp, temp + num, first);
    }

    template <typename CLType>
    CLType *read_buffer (const cl::Buffer &buf, size_type num,
            CLType *first) const
    {
        VSMC_RUNTIME_ASSERT_CL_MANAGER_SETUP(read_buffer);

        command_queue_.finish();
        command_queue_.enqueueReadBuffer(buf, 1, 0, sizeof(CLType) * num,
                (void *) first);

        return first + num;
    }

    template <typename CLType, typename InputIter>
    InputIter write_buffer (const cl::Buffer &buf, size_type num,
            InputIter first) const
    {
        VSMC_RUNTIME_ASSERT_CL_MANAGER_SETUP(write_buffer);

        CLType *temp = write_buffer_pool<CLType>(num);
        for (size_type i = 0; i != num; ++i, ++first)
            temp[i] = *first;
        command_queue_.finish();
        command_queue_.enqueueWriteBuffer(buf, 1, 0, sizeof(CLType) * num,
                (void *) temp);

        return first;
    }

    template <typename CLType>
    const CLType *write_buffer (const cl::Buffer &buf, size_type num,
            const CLType *first) const
    {
        VSMC_RUNTIME_ASSERT_CL_MANAGER_SETUP(write_buffer);

        command_queue_.finish();
        command_queue_.enqueueWriteBuffer(buf, 1, 0, sizeof(CLType) * num,
                (void *) first);

        return first + num;
    }

    template <typename CLType>
    CLType *write_buffer (const cl::Buffer &buf, size_type num,
            CLType *first) const
    {
        VSMC_RUNTIME_ASSERT_CL_MANAGER_SETUP(write_buffer);

        command_queue_.finish();
        command_queue_.enqueueWriteBuffer(buf, 1, 0, sizeof(CLType) * num,
                (void *) first);

        return first + num;
    }

    template <typename CLType>
    void copy_buffer (const cl::Buffer &src, const cl::Buffer &dst,
            size_type num) const
    {
        VSMC_RUNTIME_ASSERT_CL_MANAGER_SETUP(copy_buffer);

        command_queue_.finish();
        command_queue_.enqueueCopyBuffer(src, dst, 0, 0, num * sizeof(CLType));
        command_queue_.finish();
    }

    cl::Program create_program (const std::string &source) const
    {
        return cl::Program(context_, source);
    }

    void run_kernel (const cl::Kernel &kern,
            size_type global_size, size_type local_size) const
    {
        command_queue_.finish();
        command_queue_.enqueueNDRangeKernel(kern, cl::NullRange,
                get_global_nd_range(global_size, local_size),
                get_local_nd_range(global_size, local_size));
        command_queue_.finish();
    }

    private :

    cl::Platform platform_;
    std::vector<cl::Platform> platform_vec_;
    cl::Context context_;
    cl::Device device_;
    std::vector<cl::Device> device_vec_;
    cl::CommandQueue command_queue_;

    bool setup_;

    mutable size_type read_buffer_pool_bytes_;
    mutable size_type write_buffer_pool_bytes_;
    mutable void *read_buffer_pool_;
    mutable void *write_buffer_pool_;

    CLManager () :
        setup_(false), read_buffer_pool_bytes_(0), write_buffer_pool_bytes_(0),
        read_buffer_pool_(VSMC_NULLPTR), write_buffer_pool_(VSMC_NULLPTR)
    {
        cl_device_type dev = traits::OpenCLDeviceTypeTrait<ID>::type::value;
        if (!dev)
            dev = Default::opencl_device_type::value;
        setup_cl_manager(dev);
    }

    CLManager (const CLManager<ID> &);
    CLManager<ID> &operator= (const CLManager<ID> &);

    ~CLManager ()
    {
        std::free(read_buffer_pool_);
        std::free(write_buffer_pool_);
    }

    void setup_cl_manager (cl_device_type dev)
    {
        try {
            cl::Platform::get(&platform_vec_);
        } catch (cl::Error) {
            platform_vec_.clear();
        }

        for (std::vector<cl::Platform>::size_type p = 0;
                p != platform_vec_.size(); ++p) {
            try {
                platform_ = platform_vec_[p];
                std::string pname;
                platform_.getInfo(CL_PLATFORM_NAME, &pname);
                if (!traits::CheckOpenCLPlatformTrait<ID>::check(pname)) {
                    platform_ = cl::Platform();
                    continue;
                }

                cl_context_properties context_properties[] = {
                    CL_CONTEXT_PLATFORM,
                    (cl_context_properties)(platform_)(), 0
                };
                context_ = cl::Context(dev, context_properties);
                device_vec_ = context_.getInfo<CL_CONTEXT_DEVICES>();

                bool device_found = false;
                for (std::vector<cl::Device>::size_type d = 0;
                        d != device_vec_.size(); ++d) {
                    std::string dname;
                    device_vec_[d].getInfo(CL_DEVICE_NAME, &dname);
                    if (traits::CheckOpenCLDeviceTrait<ID>::check(dname)) {
                        device_ = device_vec_[d];
                        device_found = true;
                        break;
                    }
                }
                if (!device_found) {
                    platform_ = cl::Platform();
                    context_  = cl::Context();
                    device_   = cl::Device();
                    continue;
                }

                command_queue_ = cl::CommandQueue(context_, device_, 0);
                setup_ = true;
                break;
            } catch (cl::Error) {
                platform_      = cl::Platform();
                context_       = cl::Context();
                device_        = cl::Device();
                command_queue_ = cl::CommandQueue();
                device_vec_.clear();
            }
        }
    }

    template <typename CLType>
    CLType *read_buffer_pool (size_type num) const
    {
        size_type new_bytes = num * sizeof(CLType);
        if (new_bytes > read_buffer_pool_bytes_) {
            std::free(read_buffer_pool_);
            read_buffer_pool_ = std::malloc(new_bytes);
            if (!read_buffer_pool_ && new_bytes)
                throw std::bad_alloc();
            read_buffer_pool_bytes_ = new_bytes;
        }

        return reinterpret_cast<CLType *>(read_buffer_pool_);
    }

    template <typename CLType>
    CLType *write_buffer_pool (size_type num) const
    {
        size_type new_bytes = num * sizeof(CLType);
        if (new_bytes > write_buffer_pool_bytes_) {
            std::free(write_buffer_pool_);
            write_buffer_pool_ = std::malloc(new_bytes);
            if (!write_buffer_pool_ && new_bytes)
                throw std::bad_alloc();
            write_buffer_pool_bytes_ = new_bytes;
        }

        return reinterpret_cast<CLType *>(write_buffer_pool_);
    }

    cl::NDRange get_global_nd_range (
            size_type global_size, size_type local_size) const
    {
        return (local_size && global_size % local_size) ?
            cl::NDRange((global_size / local_size + 1) * local_size):
            cl::NDRange(global_size);
    }

    cl::NDRange get_local_nd_range (
            size_type global_size, size_type local_size) const
    {
        return local_size ? cl::NDRange(local_size) : cl::NullRange;
    }
}; // clss CLManager

} } // namespace vsmc::opencl

#endif // VSMC_UTILITY_OPENCL_MANAGER_HPP
<commit_msg>better platform verification<commit_after>#ifndef VSMC_UTILITY_OPENCL_MANAGER_HPP
#define VSMC_UTILITY_OPENCL_MANAGER_HPP

#define __CL_ENABLE_EXCEPTIONS

#include <vsmc/internal/common.hpp>
#include <vsmc/utility/opencl/cl_wrapper.hpp>

namespace vsmc { namespace opencl {

struct Default
{
    typedef cxx11::integral_constant<cl_device_type, CL_DEVICE_TYPE_DEFAULT>
        opencl_device_type;
};

struct All
{
    typedef cxx11::integral_constant<cl_device_type, CL_DEVICE_TYPE_ALL>
        opencl_device_type;
};

struct CPU
{
    typedef cxx11::integral_constant<cl_device_type, CL_DEVICE_TYPE_CPU>
        opencl_device_type;
};

struct GPU
{
    typedef cxx11::integral_constant<cl_device_type, CL_DEVICE_TYPE_GPU>
        opencl_device_type;
};

struct Accelerator
{
    typedef cxx11::integral_constant<cl_device_type,
        CL_DEVICE_TYPE_ACCELERATOR> opencl_device_type;
};

struct Apple
{
    static bool check_opencl_platform (const std::string &name)
    {return name.find(std::string("Apple")) != std::string::npos;}
};

struct Intel
{
    static bool check_opencl_platform (const std::string &name)
    {return name.find(std::string("Intel")) != std::string::npos;}
};

struct AMD
{
    static bool check_opencl_platform (const std::string &name)
    {return name.find(std::string("AMD")) != std::string::npos;}
};

struct NVIDIA
{
    static bool check_opencl_platform (const std::string &name)
    {return name.find(std::string("NVIDIA")) != std::string::npos;}
};

struct AppleCPU : public Apple, public CPU {};
struct AppleGPU : public Apple, public GPU {};

struct IntelCPU : public Intel, public CPU {};
struct IntelGPU : public Intel, public GPU {};

struct AMDCPU : public AMD, public CPU {};
struct AMDGPU : public AMD, public GPU {};

struct NVIDIACPU : public NVIDIA, public CPU {};
struct NVIDIAGPU : public NVIDIA, public GPU {};

class LocalSize
{
    public :

    LocalSize () : local_size_(0) {}

    std::size_t local_size () const
    {
        return local_size_;
    }

    void local_size (std::size_t new_size)
    {
        local_size_ = new_size;
    }

    static std::size_t preferred_local_size (
            const cl::Kernel &kern, const cl::Device &dev)
    {
        std::size_t max_s;
        std::size_t mul_s;
        kern.getWorkGroupInfo(dev, CL_KERNEL_WORK_GROUP_SIZE, &max_s);
        kern.getWorkGroupInfo(dev,
                CL_KERNEL_PREFERRED_WORK_GROUP_SIZE_MULTIPLE, &mul_s);

        return (max_s / mul_s) * mul_s;
    }

    private :

    std::size_t local_size_;
}; // class LocalSize

/// \brief OpenCL Manager
/// \ingroup OpenCL
template <typename ID>
class CLManager
{
    public :

    typedef std::size_t size_type;

    static CLManager<ID> &instance ()
    {
        static CLManager<ID> manager;

        return manager;
    }

    const cl::Platform &platform () const
    {
        return platform_;
    }

    const std::vector<cl::Platform> &platform_vec () const
    {
        return platform_vec_;
    }

    const cl::Context &context () const
    {
        return context_;
    }

    const cl::Device &device () const
    {
        return device_;
    }

    const std::vector<cl::Device> &device_vec () const
    {
        return device_vec_;
    }

    const cl::CommandQueue &command_queue () const
    {
        return command_queue_;
    }

    bool setup () const
    {
        return setup_;
    }

    void setup (cl_device_type dev)
    {
        setup_ = false;
        setup_cl_manager(dev);
    }

    void setup (const cl::Platform &plat, const cl::Context &ctx,
            const cl::Device &dev, const cl::CommandQueue &cmd)
    {
        setup_ = false;
        platform_ = plat;
        cl::Platform::get(&platform_vec_);
        context_ = ctx;
        device_ = dev;
        device_vec_ = context_.getInfo<CL_CONTEXT_DEVICES>();
        command_queue_ = cmd;
        setup_ = true;
    }

    template<typename CLType>
    cl::Buffer create_buffer (size_type num) const
    {
        VSMC_RUNTIME_ASSERT_CL_MANAGER_SETUP(create_buffer);
        VSMC_RUNTIME_ASSERT((num),
                "CALL vsmc::CLManager::crate_buffer WITH ZERO SIZE");

        if (!num)
            return cl::Buffer();

        return cl::Buffer(context_, CL_MEM_READ_WRITE, sizeof(CLType) * num);
    }

    template<typename CLType, typename InputIter>
    cl::Buffer create_buffer (InputIter first, InputIter last) const
    {
        VSMC_RUNTIME_ASSERT_CL_MANAGER_SETUP(create_buffer);

        size_type num = 0;
        for (InputIter i = first; i != last; ++i)
            ++num;

        if (!num)
            return cl::Buffer();

        cl::Buffer buf(create_buffer<CLType>(num));
        write_buffer<CLType>(buf, num, first);

        return buf;
    }

    template <typename CLType, typename OutputIter>
    OutputIter read_buffer (const cl::Buffer &buf, size_type num,
            OutputIter first) const
    {
        VSMC_RUNTIME_ASSERT_CL_MANAGER_SETUP(read_buffer);

        CLType *temp = read_buffer_pool<CLType>(num);
        command_queue_.finish();
        command_queue_.enqueueReadBuffer(buf, 1, 0, sizeof(CLType) * num,
                (void *) temp);

        return std::copy(temp, temp + num, first);
    }

    template <typename CLType>
    CLType *read_buffer (const cl::Buffer &buf, size_type num,
            CLType *first) const
    {
        VSMC_RUNTIME_ASSERT_CL_MANAGER_SETUP(read_buffer);

        command_queue_.finish();
        command_queue_.enqueueReadBuffer(buf, 1, 0, sizeof(CLType) * num,
                (void *) first);

        return first + num;
    }

    template <typename CLType, typename InputIter>
    InputIter write_buffer (const cl::Buffer &buf, size_type num,
            InputIter first) const
    {
        VSMC_RUNTIME_ASSERT_CL_MANAGER_SETUP(write_buffer);

        CLType *temp = write_buffer_pool<CLType>(num);
        for (size_type i = 0; i != num; ++i, ++first)
            temp[i] = *first;
        command_queue_.finish();
        command_queue_.enqueueWriteBuffer(buf, 1, 0, sizeof(CLType) * num,
                (void *) temp);

        return first;
    }

    template <typename CLType>
    const CLType *write_buffer (const cl::Buffer &buf, size_type num,
            const CLType *first) const
    {
        VSMC_RUNTIME_ASSERT_CL_MANAGER_SETUP(write_buffer);

        command_queue_.finish();
        command_queue_.enqueueWriteBuffer(buf, 1, 0, sizeof(CLType) * num,
                (void *) first);

        return first + num;
    }

    template <typename CLType>
    CLType *write_buffer (const cl::Buffer &buf, size_type num,
            CLType *first) const
    {
        VSMC_RUNTIME_ASSERT_CL_MANAGER_SETUP(write_buffer);

        command_queue_.finish();
        command_queue_.enqueueWriteBuffer(buf, 1, 0, sizeof(CLType) * num,
                (void *) first);

        return first + num;
    }

    template <typename CLType>
    void copy_buffer (const cl::Buffer &src, const cl::Buffer &dst,
            size_type num) const
    {
        VSMC_RUNTIME_ASSERT_CL_MANAGER_SETUP(copy_buffer);

        command_queue_.finish();
        command_queue_.enqueueCopyBuffer(src, dst, 0, 0, num * sizeof(CLType));
        command_queue_.finish();
    }

    cl::Program create_program (const std::string &source) const
    {
        return cl::Program(context_, source);
    }

    void run_kernel (const cl::Kernel &kern,
            size_type global_size, size_type local_size) const
    {
        command_queue_.finish();
        command_queue_.enqueueNDRangeKernel(kern, cl::NullRange,
                get_global_nd_range(global_size, local_size),
                get_local_nd_range(global_size, local_size));
        command_queue_.finish();
    }

    private :

    cl::Platform platform_;
    std::vector<cl::Platform> platform_vec_;
    cl::Context context_;
    cl::Device device_;
    std::vector<cl::Device> device_vec_;
    cl::CommandQueue command_queue_;

    bool setup_;

    mutable size_type read_buffer_pool_bytes_;
    mutable size_type write_buffer_pool_bytes_;
    mutable void *read_buffer_pool_;
    mutable void *write_buffer_pool_;

    CLManager () :
        setup_(false), read_buffer_pool_bytes_(0), write_buffer_pool_bytes_(0),
        read_buffer_pool_(VSMC_NULLPTR), write_buffer_pool_(VSMC_NULLPTR)
    {
        cl_device_type dev = traits::OpenCLDeviceTypeTrait<ID>::type::value;
        if (!dev)
            dev = Default::opencl_device_type::value;
        setup_cl_manager(dev);
    }

    CLManager (const CLManager<ID> &);
    CLManager<ID> &operator= (const CLManager<ID> &);

    ~CLManager ()
    {
        std::free(read_buffer_pool_);
        std::free(write_buffer_pool_);
    }

    void setup_cl_manager (cl_device_type dev)
    {
        try {
            cl::Platform::get(&platform_vec_);
        } catch (cl::Error) {
            platform_vec_.clear();
        }

        for (std::vector<cl::Platform>::size_type p = 0;
                p != platform_vec_.size(); ++p) {
            try {
                platform_ = platform_vec_[p];
                std::string pname;
                platform_.getInfo(CL_PLATFORM_NAME, &pname);
                if (!traits::CheckOpenCLPlatformTrait<ID>::check(pname)) {
                    platform_ = cl::Platform();
                    continue;
                }

                cl_context_properties context_properties[] = {
                    CL_CONTEXT_PLATFORM,
                    (cl_context_properties)(platform_)(), 0
                };
                context_ = cl::Context(dev, context_properties);
                device_vec_ = context_.getInfo<CL_CONTEXT_DEVICES>();

                bool device_found = false;
                for (std::vector<cl::Device>::size_type d = 0;
                        d != device_vec_.size(); ++d) {
                    std::string dname;
                    device_vec_[d].getInfo(CL_DEVICE_NAME, &dname);
                    if (traits::CheckOpenCLDeviceTrait<ID>::check(dname)) {
                        device_ = device_vec_[d];
                        device_found = true;
                        break;
                    }
                }
                if (!device_found) {
                    platform_ = cl::Platform();
                    context_  = cl::Context();
                    device_   = cl::Device();
                    continue;
                }

                command_queue_ = cl::CommandQueue(context_, device_, 0);
                setup_ = true;
                break;
            } catch (cl::Error) {
                platform_      = cl::Platform();
                context_       = cl::Context();
                device_        = cl::Device();
                command_queue_ = cl::CommandQueue();
                device_vec_.clear();
            }
        }
    }

    template <typename CLType>
    CLType *read_buffer_pool (size_type num) const
    {
        size_type new_bytes = num * sizeof(CLType);
        if (new_bytes > read_buffer_pool_bytes_) {
            std::free(read_buffer_pool_);
            read_buffer_pool_ = std::malloc(new_bytes);
            if (!read_buffer_pool_ && new_bytes)
                throw std::bad_alloc();
            read_buffer_pool_bytes_ = new_bytes;
        }

        return reinterpret_cast<CLType *>(read_buffer_pool_);
    }

    template <typename CLType>
    CLType *write_buffer_pool (size_type num) const
    {
        size_type new_bytes = num * sizeof(CLType);
        if (new_bytes > write_buffer_pool_bytes_) {
            std::free(write_buffer_pool_);
            write_buffer_pool_ = std::malloc(new_bytes);
            if (!write_buffer_pool_ && new_bytes)
                throw std::bad_alloc();
            write_buffer_pool_bytes_ = new_bytes;
        }

        return reinterpret_cast<CLType *>(write_buffer_pool_);
    }

    cl::NDRange get_global_nd_range (
            size_type global_size, size_type local_size) const
    {
        return (local_size && global_size % local_size) ?
            cl::NDRange((global_size / local_size + 1) * local_size):
            cl::NDRange(global_size);
    }

    cl::NDRange get_local_nd_range (
            size_type global_size, size_type local_size) const
    {
        return local_size ? cl::NDRange(local_size) : cl::NullRange;
    }
}; // clss CLManager

} } // namespace vsmc::opencl

#endif // VSMC_UTILITY_OPENCL_MANAGER_HPP
<|endoftext|>


<commit_before>///
/// @file  PrintPrimes.hpp
///
/// Copyright (C) 2018 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#ifndef PRIMEGENERATOR_HPP
#define PRIMEGENERATOR_HPP

#include "config.hpp"
#include "Erat.hpp"
#include "PrimeSieve.hpp"
#include "PreSieve.hpp"

#include <stdint.h>
#include <vector>

namespace primesieve {

class Store;

/// After a segment has been sieved PrintPrimes is
/// used to reconstruct primes and prime k-tuplets from
/// 1 bits of the sieve array
///
class PrintPrimes : public Erat
{
public:
  PrintPrimes(PrimeSieve&);
  void sieve();
private:
  enum { END = 0xff + 1 };
  static const uint64_t bitmasks_[6][5];
  /// Count lookup tables for prime k-tuplets
  std::vector<byte_t> kCounts_[6];
  /// Reference to the associated PrimeSieve object
  PreSieve preSieve_;
  PrimeSieve::counts_t& counts_;
  PrimeSieve& ps_;
  virtual void generatePrimes(const byte_t*, uint64_t);
  void initCounts();
  void countPrimes(const byte_t*, uint64_t);
  void countkTuplets(const byte_t*, uint64_t);
  void printPrimes(const byte_t*, uint64_t) const;
  void printkTuplets(const byte_t*, uint64_t) const;
};

} // namespace

#endif
<commit_msg>Refactor<commit_after>///
/// @file  PrintPrimes.hpp
///
/// Copyright (C) 2018 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#ifndef PRIMEGENERATOR_HPP
#define PRIMEGENERATOR_HPP

#include "config.hpp"
#include "Erat.hpp"
#include "PrimeSieve.hpp"
#include "PreSieve.hpp"

#include <stdint.h>
#include <vector>

namespace primesieve {

class Store;

/// After a segment has been sieved PrintPrimes is
/// used to reconstruct primes and prime k-tuplets from
/// 1 bits of the sieve array
///
class PrintPrimes : public Erat
{
public:
  PrintPrimes(PrimeSieve&);
  void sieve();
private:
  enum { END = 0xff + 1 };
  static const uint64_t bitmasks_[6][5];
  /// Count lookup tables for prime k-tuplets
  std::vector<byte_t> kCounts_[6];
  /// Reference to the associated PrimeSieve object
  PreSieve preSieve_;
  PrimeSieve::counts_t& counts_;
  PrimeSieve& ps_;
  void initCounts();
  void generatePrimes(const byte_t*, uint64_t);
  void countPrimes(const byte_t*, uint64_t);
  void countkTuplets(const byte_t*, uint64_t);
  void printPrimes(const byte_t*, uint64_t) const;
  void printkTuplets(const byte_t*, uint64_t) const;
};

} // namespace

#endif
<|endoftext|>


<commit_before>//===- seec/Util/TypeHandling.hpp ----------------------------------- C++ -===//
//
//
//
//===----------------------------------------------------------------------===//
//
//
//
//===----------------------------------------------------------------------===//

#ifndef _SEEC_UTIL_TYPE_HANDLING_HPP_
#define _SEEC_UTIL_TYPE_HANDLING_HPP_

namespace seec {

/// \name Remove pointers from a type.
/// @{

template<typename T>
struct Pointee { typedef T Type; };

template<typename T>
struct Pointee<T *> { typedef T Type; };

template<typename T>
struct Pointee<T * const> { typedef T Type; };

template<typename T>
struct StripPointers { typedef T Type; };

template<typename T>
struct StripPointers<T *> { typedef typename StripPointers<T>::Type Type; };

template<typename T>
struct StripPointers<T * const> {
  typedef typename StripPointers<T>::Type Type;
};

/// @}

/// \name Remove const from a type.
/// @{

template<typename T>
struct StripConst { typedef T Type; };

template<typename T>
struct StripConst<T const> { typedef T Type; };

/// @}

/// \name Remove (const) pointers, (const) references, and consts from a type.
/// @{

template<typename T>
struct StripAll { typedef T Type; };

template<typename T>
struct StripAll<T *> { typedef typename StripAll<T>::Type Type; };

template<typename T>
struct StripAll<T &> { typedef typename StripAll<T>::Type Type; };

template<typename T>
struct StripAll<T &&> { typedef typename StripAll<T>::Type Type; };

template<typename T>
struct StripAll<T const> { typedef typename StripAll<T>::Type Type; };

/// @}

} // namespace seec

#endif // _SEEC_UTIL_TYPE_HANDLING_HPP_
<commit_msg>Remove unused header file.<commit_after><|endoftext|>


<commit_before><commit_msg>Ensure ref values are strings<commit_after><|endoftext|>