<commit_before>#include "stdafx.h"

#include "CoreDelegateImpl.h"

#include <GameCore/Core.h>
#include <GameCore/Render/IRenderer.h>
#include <GameCore/Render/HardwareBufferManagerBase.h>
#include <GameCore/Input/inputsystem.h>
#include <GameCore/Render/OpenGL/GlUitlities.h>
#include <GameCore/Render/TextureManager.h>

// for test
#include <GL/glew.h>
#include <GL/GL.h>
#include <GL/GLU.h>
#define BUFFER_OFFSET(i) ((char *)NULL + (i))
#include <time.h>

#include <Math/Matrix4.h>

using namespace SDK;

#pragma comment(lib, "opengl32.lib")
#if defined(_DEBUG)
# pragma comment(lib, "glew32d.lib")
#else
# pragma comment(lib, "glew32.lib")
#endif

#include <GameCore/Applications/ApplicationBase.h>

#include <GameCore/Render/MeshSystem.h>
#include <GameCore/Render/MaterialManager.h>
#include <GameCore/Systems/TransformationsSystem.h>

#include <GameCore/Render/ShaderSystem.h>
#include <GameCore/EntityManager.h>
#include <GameCore/Render/LightsController.h>
#include <GameCore/Render/ScopedLightSwitch.h>
#include <GameCore/PropertyElement.h>
#include <GameCore/Resources/ResourceManager.h>
#include <GameCore/Render/ShaderCompiler.h>

namespace Game
{
	EntityHandle entity_handler;
	void CoreDelegateImpl::LoadModel()
	{
		//E:\Git_Projects\SupportSDK\Samples\Resources\Models\Box.obj
		//loaded_mesh = Render::g_mesh_system.Load("Resources\\Models\\Box.obj", Render::BufferUsageFormat::Static, Render::BufferUsageFormat::Static);
		auto p_load_manager = Core::GetGlobalObject<Resources::ResourceManager>();
		loaded_mesh = p_load_manager->GetHandleToResource<Render::Mesh>("Nanosuit");

		auto mesh_handler = Render::g_mesh_system.CreateInstance(loaded_mesh);
		auto trans_handler = g_transforms_system.CreateInstance();
		auto p_transform = g_transforms_system.GetInstance(trans_handler);

		entity_handler = g_entity_manager.CreateEntity();
		g_entity_manager.AddComponent<Render::MeshComponent>(entity_handler, mesh_handler);
		g_entity_manager.AddComponent<Transform>(entity_handler, trans_handler);

		// test getting of entity and component
		auto entity = g_entity_manager.GetEntity(entity_handler);

		Render::MaterialHandle material_handle = p_load_manager->GetHandleToResource<Render::Material>("Nanosuit_material");
		auto p_material = Render::g_material_mgr.AccessMaterial(material_handle);

		Render::g_mesh_system.AddMaterialTo(mesh_handler, material_handle);
	}

	void CoreDelegateImpl::CreateMesh()
	{
		auto p_renderer = Core::GetRenderer();
		auto p_mgr = p_renderer->GetHardwareBufferMgr();

	}

	void CoreDelegateImpl::OnCreate()
	{
		InputSystem::Instance().AddSubscriber(&m_input_subs);
		auto p_load_manager = Core::GetGlobalObject<Resources::ResourceManager>();
		p_load_manager->LoadResourceSet("..\\..\\Resources\\ResourceSets\\render_testing.res");

		LoadModel();

		CreateMesh();

		auto& world = Core::GetApplication()->GetWorld();
		auto& camera = world.GetCamera();

		camera.LookAt({ 0,-5,-15 }, { -10,-2,0 });

		world.GetFrustum().SetFOV(60 * Math::DEG2RAD);
	}

	void CoreDelegateImpl::OnTerminate()
	{
		InputSystem::Instance().RemoveSubscriber(&m_input_subs);

		auto p_renderer = Core::GetRenderer();
		p_renderer->GetHardwareBufferMgr()->DestroyBuffer(batch[0].vertices);
		p_renderer->GetHardwareBufferMgr()->DestroyBuffer(batch[0].indices);
		p_renderer->GetHardwareBufferMgr()->DestroyBuffer(batch[0].vertices);

		p_renderer->GetHardwareBufferMgr()->DestroyBuffer(batch[1].vertices);
		p_renderer->GetHardwareBufferMgr()->DestroyBuffer(batch[1].indices);
		p_renderer->GetHardwareBufferMgr()->DestroyBuffer(batch[1].vertices);

		g_entity_manager.RemoveEntity(entity_handler);

		auto p_load_manager = Core::GetGlobalObject<Resources::ResourceManager>();
		p_load_manager->UnloadSet(p_load_manager->GetHandleToSet("render_testing"));
	}

	void CoreDelegateImpl::Update(float i_elapsed_time)
	{
	}

	void CoreDelegateImpl::Draw()
	{
	}

} // Game<commit_msg>[Samples] Maintenance<commit_after>#include "stdafx.h"

#include "CoreDelegateImpl.h"

#include <GameCore/Core.h>
#include <GameCore/Render/IRenderer.h>
#include <GameCore/Render/HardwareBufferManagerBase.h>
#include <GameCore/Input/inputsystem.h>
#include <GameCore/Render/OpenGL/GlUitlities.h>
#include <GameCore/Render/TextureManager.h>

// for test
#include <GL/glew.h>
#include <GL/GL.h>
#include <GL/GLU.h>
#define BUFFER_OFFSET(i) ((char *)NULL + (i))
#include <time.h>

#include <Math/Matrix4.h>

using namespace SDK;

#pragma comment(lib, "opengl32.lib")
#if defined(_DEBUG)
# pragma comment(lib, "glew32d.lib")
#else
# pragma comment(lib, "glew32.lib")
#endif

#include <GameCore/Applications/ApplicationBase.h>

#include <GameCore/Render/MeshSystem.h>
#include <GameCore/Render/MaterialManager.h>
#include <GameCore/Systems/TransformationsSystem.h>

#include <GameCore/Render/ShaderSystem.h>
#include <GameCore/EntityManager.h>
#include <GameCore/Render/LightsController.h>
#include <GameCore/Render/ScopedLightSwitch.h>
#include <GameCore/PropertyElement.h>
#include <GameCore/Resources/ResourceManager.h>
#include <GameCore/Render/ShaderCompiler.h>

namespace Game
{
	EntityHandle entity_handler;
	void CoreDelegateImpl::LoadModel()
	{
		//E:\Git_Projects\SupportSDK\Samples\Resources\Models\Box.obj
		//loaded_mesh = Render::g_mesh_system.Load("Resources\\Models\\Box.obj", Render::BufferUsageFormat::Static, Render::BufferUsageFormat::Static);
		auto p_load_manager = Core::GetGlobalObject<Resources::ResourceManager>();
		loaded_mesh = p_load_manager->GetHandleToResource<Render::Mesh>("SimpleBox");

		auto mesh_handler = Render::g_mesh_system.CreateInstance(loaded_mesh);
		auto trans_handler = g_transforms_system.CreateInstance();
		auto p_transform = g_transforms_system.GetInstance(trans_handler);

		entity_handler = g_entity_manager.CreateEntity();
		g_entity_manager.AddComponent<Render::MeshComponent>(entity_handler, mesh_handler);
		g_entity_manager.AddComponent<Transform>(entity_handler, trans_handler);

		// test getting of entity and component
		auto entity = g_entity_manager.GetEntity(entity_handler);

		Render::MaterialHandle material_handle = p_load_manager->GetHandleToResource<Render::Material>("Sample_material");
		auto p_material = Render::g_material_mgr.AccessMaterial(material_handle);

		Render::g_mesh_system.AddMaterialTo(mesh_handler, material_handle);
	}

	void CoreDelegateImpl::CreateMesh()
	{
		auto p_renderer = Core::GetRenderer();
		auto p_mgr = p_renderer->GetHardwareBufferMgr();

	}

	void CoreDelegateImpl::OnCreate()
	{
		InputSystem::Instance().AddSubscriber(&m_input_subs);
		auto p_load_manager = Core::GetGlobalObject<Resources::ResourceManager>();
		p_load_manager->LoadResourceSet("..\\..\\Resources\\ResourceSets\\render_testing.res");

		LoadModel();

		CreateMesh();

		auto& world = Core::GetApplication()->GetWorld();
		auto& camera = world.GetCamera();

		camera.LookAt({ 0,-5,-15 }, { -10,-2,0 });

		world.GetFrustum().SetFOV(60 * Math::DEG2RAD);
	}

	void CoreDelegateImpl::OnTerminate()
	{
		InputSystem::Instance().RemoveSubscriber(&m_input_subs);

		auto p_renderer = Core::GetRenderer();
		p_renderer->GetHardwareBufferMgr()->DestroyBuffer(batch[0].vertices);
		p_renderer->GetHardwareBufferMgr()->DestroyBuffer(batch[0].indices);
		p_renderer->GetHardwareBufferMgr()->DestroyBuffer(batch[0].vertices);

		p_renderer->GetHardwareBufferMgr()->DestroyBuffer(batch[1].vertices);
		p_renderer->GetHardwareBufferMgr()->DestroyBuffer(batch[1].indices);
		p_renderer->GetHardwareBufferMgr()->DestroyBuffer(batch[1].vertices);

		g_entity_manager.RemoveEntity(entity_handler);

		auto p_load_manager = Core::GetGlobalObject<Resources::ResourceManager>();
		p_load_manager->UnloadSet(p_load_manager->GetHandleToSet("render_testing"));
	}

	void CoreDelegateImpl::Update(float i_elapsed_time)
	{
	}

	void CoreDelegateImpl::Draw()
	{
	}

} // Game<|endoftext|>


<commit_before>#include <ontology/olink.h>

/********************************************************************************
 * Print out the link information
 ********************************************************************************/
void Olink::printLink(){
  if (valued){
  cout << "\t\tLink Name: " << name << " Nodes (" << start_node << "," << end_node << ") V: " << value << "\n";
  } else {
  cout << "\t\tLink Name: " << name << " Nodes (" << start_node << "," << end_node << ")\n";
  }
}

/********************************************************************************
 * Constructor function with no info
 ********************************************************************************/
Olink::Olink(){

  valued = false;

}

/********************************************************************************
 * Constructor function with all info
 ********************************************************************************/
Olink::Olink(string n_name, int node1, int node2){

  name = n_name;
  start_node = node1;
  end_node = node2;
  valued = false;

}

/********************************************************************************
 * Set the name of the link
 ********************************************************************************/
void Olink::setName(string n_name){

  name = n_name;
}

/********************************************************************************
 * Set the starting node of the link
 ********************************************************************************/
void Olink::setStart(int node_id){

  start_node = node_id;

}

/********************************************************************************
 * Set the ending node of the link
 ********************************************************************************/
void Olink::setEnd(int node_id){

  end_node = node_id;

}

/********************************************************************************
 * Set all the information of the node
 ********************************************************************************/
void Olink::setInfo(string n_name, int node1, int node2){

  name = n_name;
  start_node = node1;
  end_node = node2;

}

/********************************************************************************
 * Set all the information of the node
 ********************************************************************************/
void Olink::setInfo2(string n_name, int node2){

  name = n_name;
  end_node = node2;

}

/********************************************************************************
 * Set the value of the node, and set the valued parameter to be true
 ********************************************************************************/
void Olink::setValue(int v){

  value = v;
  valued = true;

}

/********************************************************************************
 * Return the id of the start node of the link
 ********************************************************************************/
int Olink::getStart(){

  return start_node;

}

/********************************************************************************
 * Return the id of the end node of the link
 ********************************************************************************/
int Olink::getEnd(){

  return end_node;

}

/********************************************************************************
 * Return the name of the link
 ********************************************************************************/
string Olink::getName(){

  return name;

}

/********************************************************************************
 * Does the link have a value associated with it?
 ********************************************************************************/
bool Olink::isValued(){

  return valued;

}

/********************************************************************************
 * Return the value of the link
 ********************************************************************************/
int Olink::getValue(){

  return value;

}
<commit_msg>Refactored olink.cpp<commit_after>#include <ontology/olink.h>

/********************************************************************************
* Print out the link information
********************************************************************************/
void Olink::printLink() const
{
    if( _is_valued )
    {
        std::cerr << "\t\tLink Name: " << _name << " Nodes (" << _start_node << "," << _end_node << ") V: " << _value << std::endl;
    }
    else
    {
        std::cerr << "\t\tLink Name: " << _name << " Nodes (" << _start_node << "," << _end_node << ")" << std::endl;
    }
}

/********************************************************************************
* Constructor function with no info
********************************************************************************/
Olink::Olink()
{
    _is_valued = false;
}

/********************************************************************************
* Constructor function with all info
********************************************************************************/
Olink::Olink( std::string const & name, int const & node1, int const & node2 )
{
    _name = name;
    _start_node = node1;
    _end_node = node2;
    _is_valued = false;
}

/********************************************************************************
* Set the name of the link
********************************************************************************/
void Olink::setName( std::string const & name )
{
    _name = name;
}

/********************************************************************************
* Set the starting node of the link
********************************************************************************/
void Olink::setStart( int const & node_id )
{
    _start_node = node_id;
}

/********************************************************************************
* Set the ending node of the link
********************************************************************************/
void Olink::setEnd( int const & node_id )
{
    _end_node = node_id;
}

/********************************************************************************
* Set all the information of the node
********************************************************************************/
void Olink::setInfo( std::string const & name, int const & node1, int const & node2 )
{
    _name = name;
    _start_node = node1;
    _end_node = node2;
}

/********************************************************************************
* Set all the information of the node
********************************************************************************/
void Olink::setInfo2( std::string const & name, int const & node2 )
{
    _name = name;
    _end_node = node2;
}

/********************************************************************************
* Set the value of the node, and set the valued parameter to be true
********************************************************************************/
void Olink::setValue( int const & value )
{
    _value = value;
    _is_valued = true;
}

/********************************************************************************
* Return the id of the start node of the link
********************************************************************************/
int const & Olink::getStart() const
{
    return _start_node;
}

/********************************************************************************
* Return the id of the end node of the link
********************************************************************************/
int const & Olink::getEnd() const
{
    return _end_node;
}

/********************************************************************************
* Return the name of the link
********************************************************************************/
std::string const & Olink::getName() const
{
    return _name;
}

/********************************************************************************
* Does the link have a value associated with it?
********************************************************************************/
bool const & Olink::isValued() const
{
    return _is_valued;
}

/********************************************************************************
* Return the value of the link
********************************************************************************/
int const & Olink::getValue() const
{
    return _value;
}
<|endoftext|>


<commit_before>/*
 *  Copyright (c) 2010
 *    Hugo Stefan Kaus Puhlmann <hugopuhlmann@gmail.com>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
*/

#include "TableMatrix.h"
#include "Table.h"

namespace rty
{
	TableMatrix::TableMatrix(int l, int c)
		: rows(l), cols(c)
	{
		mat = new Table*[l];
		for(int i = 0; i < l; i++)
			mat[i] = new Table[c];
		ngrupos = 0;
		int table_num = 0;
		for(int i = 0; i < l; i++)
		{
			for(int j = 0; j < c; j++)
				mat[i][j].num = table_num++;
		}
	}

	htl::vector<Table*> TableMatrix::getTableGroup(unsigned int s)
	{
		htl::vector<Table*> vec;
		vec.reserve(s + s%Table::MAX_OCCUPANTS / Table::MAX_OCCUPANTS);

		if(s == 0)
			return vec;

		if(s <= 2)
		{
			for(int i = 0; i < rows; i++)
			{
				for(int j = 0; j < cols; j++)
				{
					if(mat[i][j].free == mat[i][j].MAX_OCCUPANTS)
					{
						vec.push_back(&mat[i][j]);
						break;
					}
				}
				if(!vec.empty())
					break;
			}
		}

		if(s > 2)
		{
			for(int i = 0; i < rows; i++)
			{
				for(int j = 0; j < cols; j++)
				{
					vec = findAround(i, j, s);
					if(!vec.empty())
						break;
				}
				if(!vec.empty())
					break;
			}
		}

		for(htl::vector<Table*>::iterator it = vec.begin(); it != vec.end(); it++)
		{
			(*it)->free -= (*it)->MAX_OCCUPANTS - s%2;
			s -= (*it)->MAX_OCCUPANTS - s%2;
		}

		return vec;
	}

	htl::vector<Table*>	TableMatrix::findAround(int row, int column, int n)
	{
		htl::vector<Table*> tab;

		for (int i = 0; i + row < rows; ++i)
		{
			if(mat[i + row][column].free == Table::MAX_OCCUPANTS)
			{
				tab.push_back(&mat[i + row][column]);
				if(int(tab.size()) >= n/Table::MAX_OCCUPANTS)
					return tab;
			}
		}

		for (int i = -1; i + row > 0; --i)
		{
			if(mat[i + row][column].free == Table::MAX_OCCUPANTS)
			{
				tab.push_back(&mat[i + row][column]);
				if(int(tab.size()) >= n/Table::MAX_OCCUPANTS)
					return tab;
			}
			else
				break;
		}

		for (int i = 1; i + column < cols; ++i)
		{
			if(mat[row][column + i].free == Table::MAX_OCCUPANTS)
			{
				tab.push_back(&mat[row][column + i]);
				if(int(tab.size()) >= n/Table::MAX_OCCUPANTS)
					return tab;

			}
			else
				break;
		}

		for (int i = -1; i + column > 0; i--)
		{
			if(mat[row][column + i].free == Table::MAX_OCCUPANTS)
			{
				tab.push_back(&mat[row][column + i]);
				if(int(tab.size()) >= n/Table::MAX_OCCUPANTS)
					return tab;
			}
			else
				break;
		}

		tab.clear();
		return tab;
	}
}<commit_msg>fixing a problem with odd numer of clients<commit_after>/*
 *  Copyright (c) 2010
 *    Hugo Stefan Kaus Puhlmann <hugopuhlmann@gmail.com>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
*/

#include "TableMatrix.h"
#include "Table.h"

namespace rty
{
	TableMatrix::TableMatrix(int l, int c)
		: rows(l), cols(c)
	{
		mat = new Table*[l];
		for(int i = 0; i < l; i++)
			mat[i] = new Table[c];
		ngrupos = 0;
		int table_num = 0;
		for(int i = 0; i < l; i++)
		{
			for(int j = 0; j < c; j++)
				mat[i][j].num = table_num++;
		}
	}

	htl::vector<Table*> TableMatrix::getTableGroup(unsigned int s)
	{
		htl::vector<Table*> vec;
		vec.reserve(s + s%Table::MAX_OCCUPANTS / Table::MAX_OCCUPANTS);

		if(s == 0)
			return vec;

		if(s <= 2)
		{
			for(int i = 0; i < rows; i++)
			{
				for(int j = 0; j < cols; j++)
				{
					if(mat[i][j].free == mat[i][j].MAX_OCCUPANTS)
					{
						vec.push_back(&mat[i][j]);
						break;
					}
				}
				if(!vec.empty())
					break;
			}
		}

		if(s > 2)
		{
			for(int i = 0; i < rows; i++)
			{
				for(int j = 0; j < cols; j++)
				{
					vec = findAround(i, j, s);
					if(!vec.empty())
						break;
				}
				if(!vec.empty())
					break;
			}
		}

		for(htl::vector<Table*>::iterator it = vec.begin(); it != vec.end(); it++)
		{
			(*it)->free -= (*it)->MAX_OCCUPANTS - s%2;
			s -= (*it)->MAX_OCCUPANTS - s%2;
		}

		return vec;
	}

	htl::vector<Table*>	TableMatrix::findAround(int row, int column, int n)
	{
		htl::vector<Table*> tab;

		for (int i = 0; i + row < rows; ++i)
		{
			if(mat[i + row][column].free == Table::MAX_OCCUPANTS)
			{
				tab.push_back(&mat[i + row][column]);
				if(int(tab.size()) >= (n + n%Table::MAX_OCCUPANTS)/Table::MAX_OCCUPANTS)
					return tab;
			}
		}

		for (int i = -1; i + row > 0; --i)
		{
			if(mat[i + row][column].free == Table::MAX_OCCUPANTS)
			{
				tab.push_back(&mat[i + row][column]);
				if(int(tab.size()) >= (n + n%Table::MAX_OCCUPANTS)/Table::MAX_OCCUPANTS)
					return tab;
			}
			else
				break;
		}

		for (int i = 1; i + column < cols; ++i)
		{
			if(mat[row][column + i].free == Table::MAX_OCCUPANTS)
			{
				tab.push_back(&mat[row][column + i]);
				if(int(tab.size()) >= (n + n%Table::MAX_OCCUPANTS)/Table::MAX_OCCUPANTS)
					return tab;

			}
			else
				break;
		}

		for (int i = -1; i + column > 0; i--)
		{
			if(mat[row][column + i].free == Table::MAX_OCCUPANTS)
			{
				tab.push_back(&mat[row][column + i]);
				if(int(tab.size()) >= (n + n%Table::MAX_OCCUPANTS)/Table::MAX_OCCUPANTS)
					return tab;
			}
			else
				break;
		}

		tab.clear();
		return tab;
	}
}<|endoftext|>


<commit_before>#include <sstream>
#include <fcntl.h>

#include "Array.h"
#include "ObjectIO.h"
#include "VM.h"

namespace magpie
{
  using std::ostream;

  gc<BufferObject> asBuffer(gc<Object> obj)
  {
    return static_cast<BufferObject*>(&(*obj));
  }

  gc<FileObject> asFile(gc<Object> obj)
  {
    return static_cast<FileObject*>(&(*obj));
  }

  gc<StreamObject> asStream(gc<Object> obj)
  {
    return static_cast<StreamObject*>(&(*obj));
  }

  FSTask::FSTask(gc<Fiber> fiber)
  : Task(fiber)
  {
    fs_.data = this;
  }

  FSTask::~FSTask()
  {
    uv_fs_req_cleanup(&fs_);
  }

  void FSTask::kill()
  {
    uv_cancel(reinterpret_cast<uv_req_t*>(&fs_));
  }

  FSReadTask::FSReadTask(gc<Fiber> fiber, int bufferSize)
  : FSTask(fiber)
  {
    buffer_ = BufferObject::create(bufferSize);
  }

  void FSReadTask::reach()
  {
    FSTask::reach();
    buffer_.reach();
  }

  HandleTask::HandleTask(gc<Fiber> fiber, uv_handle_t* handle)
  : Task(fiber),
    handle_(handle)
  {
    handle_->data = this;
  }

  HandleTask::~HandleTask()
  {
    delete handle_;
  }

  void HandleTask::kill()
  {
    uv_unref(handle_);
    delete handle_;
    handle_ = NULL;
  }

  gc<BufferObject> BufferObject::create(int count)
  {
    // Allocate enough memory for the buffer and its data.
    void* mem = Memory::allocate(sizeof(BufferObject) +
                                 sizeof(unsigned char) * (count - 1));

    // Construct it by calling global placement new.
    gc<BufferObject> buffer = ::new(mem) BufferObject(count);

    // Fill with zero.
    for (int i = 0; i < count; i++)
    {
      buffer->bytes_[i] = 0;
    }

    return buffer;
  }

  gc<ClassObject> BufferObject::getClass(VM& vm) const
  {
    return vm.bufferClass();
  }

  gc<String> BufferObject::toString() const
  {
    if (count_ == 0) return String::create("[buffer]");

    gc<String> result = String::create("[buffer");

    if (count_ <= 8)
    {
      // Small buffer, so show the whole contents.
      for (int i = 0; i < count_; i++)
      {
        result = String::format("%s %02x", result->cString(), bytes_[i]);
      }
    }
    else
    {
      // Long buffer, so just shows the first and last few octets.
      for (int i = 0; i < 4; i++)
      {
        result = String::format("%s %02x", result->cString(), bytes_[i]);
      }

      result = String::format("%s ...", result->cString());

      for (int i = count_ - 4; i < count_; i++)
      {
        result = String::format("%s %02x", result->cString(), bytes_[i]);
      }
    }

    return String::format("%s]", result->cString());
  }

  void BufferObject::truncate(int count)
  {
    ASSERT(count <= count_, "Cannot truncate to a larger size.");
    count_ = count;
  }

  static void openFileCallback(uv_fs_t* handle)
  {
    // TODO(bob): Handle errors!
    Task* task = static_cast<Task*>(handle->data);

    // Note that the file descriptor is returned in [result] and not [file].
    task->complete(new FileObject(handle->result));
  }

  void FileObject::open(gc<Fiber> fiber, gc<String> path)
  {
    FSTask* task = new FSTask(fiber);

    // TODO(bob): Make this configurable.
    int flags = O_RDONLY;
    // TODO(bob): Make this configurable when creating a file.
    int mode = 0;
    uv_fs_open(task->loop(), task->request(), path->cString(), flags, mode,
               openFileCallback);
  }

  static void getSizeCallback(uv_fs_t* handle)
  {
    // TODO(bob): Handle errors!
    Task* task = static_cast<Task*>(handle->data);
    uv_statbuf_t* statbuf = static_cast<uv_statbuf_t*>(handle->ptr);
    task->complete(new IntObject(statbuf->st_size));
  }

  void FileObject::getSize(gc<Fiber> fiber)
  {
    FSTask* task = new FSTask(fiber);
    uv_fs_fstat(task->loop(), task->request(), file_, getSizeCallback);
  }

  // TODO(bob): Stream-based code. Saving it for later.
  /*
   static uv_buf_t allocateCallback(uv_handle_t *handle, size_t suggested_size)
   {
   printf("Alloc %ld\n", suggested_size);
   // TODO(bob): Don't use malloc() here.
   return uv_buf_init((char*) malloc(suggested_size), suggested_size);
   }

   static void readCallback(uv_stream_t *stream, ssize_t nread, uv_buf_t buf)
   {
   // TODO(bob): Implement me!
   printf("Read %ld bytes\n", nread);
   }
   */

  static void readBytesCallback(uv_fs_t *request)
  {
    // TODO(bob): Handle errors!
    FSReadTask* task = reinterpret_cast<FSReadTask*>(request->data);

    gc<Object> result = task->buffer();
    if (request->result != 0)
    {
      // Trim the buffer to the actually read size.
      task->buffer()->truncate(request->result);
    }
    else
    {
      // If we read when at EOF, return done.
      result = task->fiber()->vm().getBuiltIn(BUILT_IN_DONE);
    }

    task->complete(result);
  }

  void FileObject::readBytes(gc<Fiber> fiber, int size)
  {
    FSReadTask* task = new FSReadTask(fiber, size);

    // TODO(bob): Check result.
    uv_fs_read(task->loop(), task->request(), file_,
               task->buffer()->data(), task->buffer()->count(), -1,
               readBytesCallback);

    // TODO(bob): Use this for the streaming methods:
    /*
     // TODO(bob): What if you call read on the same file multiple times?
     // Should the pipe be reused?
     // Get a pipe to the file.
     uv_pipe_t* pipe = tasks_.createPipe(fiber);
     uv_pipe_init(loop_, pipe, 0);
     uv_pipe_open(pipe, file->file());

     // TODO(bob): Check result.
     uv_read_start(reinterpret_cast<uv_stream_t*>(pipe), allocateCallback,
     readCallback);
     */
  }

  static void closeFileCallback(uv_fs_t* handle)
  {
    Task* task = static_cast<Task*>(handle->data);

    // Close returns nothing.
    task->complete(NULL);
  }

  void FileObject::close(gc<Fiber> fiber)
  {
    ASSERT(isOpen_, "IO library should not call close on a closed file.");
    // Mark the file closed immediately so other fibers can't try to use it.
    isOpen_ = false;

    FSTask* task = new FSTask(fiber);
    uv_fs_close(task->loop(), task->request(), file_,
                closeFileCallback);
  }

  gc<ClassObject> FileObject::getClass(VM& vm) const
  {
    return vm.fileClass();
  }

  gc<String> FileObject::toString() const
  {
    // TODO(bob): Include some kind of ID or something here.
    return String::create("[file]");
  }

  void FileObject::reach()
  {
    // TODO(bob): How should we handle file_ here?
  }

  gc<ClassObject> StreamObject::getClass(VM& vm) const
  {
    return vm.streamClass();
  }

  gc<String> StreamObject::toString() const
  {
    // TODO(bob): Include some kind of ID or something here.
    return String::create("[stream]");
  }
}
<commit_msg>Add TODO.<commit_after>#include <sstream>
#include <fcntl.h>

#include "Array.h"
#include "ObjectIO.h"
#include "VM.h"

namespace magpie
{
  using std::ostream;

  gc<BufferObject> asBuffer(gc<Object> obj)
  {
    return static_cast<BufferObject*>(&(*obj));
  }

  gc<FileObject> asFile(gc<Object> obj)
  {
    return static_cast<FileObject*>(&(*obj));
  }

  gc<StreamObject> asStream(gc<Object> obj)
  {
    return static_cast<StreamObject*>(&(*obj));
  }

  FSTask::FSTask(gc<Fiber> fiber)
  : Task(fiber)
  {
    fs_.data = this;
  }

  FSTask::~FSTask()
  {
    uv_fs_req_cleanup(&fs_);
  }

  void FSTask::kill()
  {
    uv_cancel(reinterpret_cast<uv_req_t*>(&fs_));
  }

  FSReadTask::FSReadTask(gc<Fiber> fiber, int bufferSize)
  : FSTask(fiber)
  {
    buffer_ = BufferObject::create(bufferSize);
  }

  void FSReadTask::reach()
  {
    FSTask::reach();
    buffer_.reach();
  }

  HandleTask::HandleTask(gc<Fiber> fiber, uv_handle_t* handle)
  : Task(fiber),
    handle_(handle)
  {
    handle_->data = this;
  }

  HandleTask::~HandleTask()
  {
    delete handle_;
  }

  void HandleTask::kill()
  {
    uv_unref(handle_);
    delete handle_;
    handle_ = NULL;
  }

  gc<BufferObject> BufferObject::create(int count)
  {
    // Allocate enough memory for the buffer and its data.
    void* mem = Memory::allocate(sizeof(BufferObject) +
                                 sizeof(unsigned char) * (count - 1));

    // Construct it by calling global placement new.
    gc<BufferObject> buffer = ::new(mem) BufferObject(count);

    // Fill with zero.
    for (int i = 0; i < count; i++)
    {
      buffer->bytes_[i] = 0;
    }

    return buffer;
  }

  gc<ClassObject> BufferObject::getClass(VM& vm) const
  {
    return vm.bufferClass();
  }

  gc<String> BufferObject::toString() const
  {
    if (count_ == 0) return String::create("[buffer]");

    gc<String> result = String::create("[buffer");

    if (count_ <= 8)
    {
      // Small buffer, so show the whole contents.
      for (int i = 0; i < count_; i++)
      {
        result = String::format("%s %02x", result->cString(), bytes_[i]);
      }
    }
    else
    {
      // Long buffer, so just shows the first and last few octets.
      for (int i = 0; i < 4; i++)
      {
        result = String::format("%s %02x", result->cString(), bytes_[i]);
      }

      result = String::format("%s ...", result->cString());

      for (int i = count_ - 4; i < count_; i++)
      {
        result = String::format("%s %02x", result->cString(), bytes_[i]);
      }
    }

    return String::format("%s]", result->cString());
  }

  void BufferObject::truncate(int count)
  {
    ASSERT(count <= count_, "Cannot truncate to a larger size.");
    count_ = count;
  }

  static void openFileCallback(uv_fs_t* handle)
  {
    // TODO(bob): Handle errors!
    Task* task = static_cast<Task*>(handle->data);

    // Note that the file descriptor is returned in [result] and not [file].
    task->complete(new FileObject(handle->result));
  }

  void FileObject::open(gc<Fiber> fiber, gc<String> path)
  {
    FSTask* task = new FSTask(fiber);

    // TODO(bob): Make this configurable.
    int flags = O_RDONLY;
    // TODO(bob): Make this configurable when creating a file.
    int mode = 0;
    uv_fs_open(task->loop(), task->request(), path->cString(), flags, mode,
               openFileCallback);
  }

  static void getSizeCallback(uv_fs_t* handle)
  {
    // TODO(bob): Handle errors!
    Task* task = static_cast<Task*>(handle->data);
    // TODO(bob): Use handle.statbuf after upgrading to latest libuv where
    // that's public.
    uv_statbuf_t* statbuf = static_cast<uv_statbuf_t*>(handle->ptr);
    task->complete(new IntObject(statbuf->st_size));
  }

  void FileObject::getSize(gc<Fiber> fiber)
  {
    FSTask* task = new FSTask(fiber);
    uv_fs_fstat(task->loop(), task->request(), file_, getSizeCallback);
  }

  // TODO(bob): Stream-based code. Saving it for later.
  /*
   static uv_buf_t allocateCallback(uv_handle_t *handle, size_t suggested_size)
   {
   printf("Alloc %ld\n", suggested_size);
   // TODO(bob): Don't use malloc() here.
   return uv_buf_init((char*) malloc(suggested_size), suggested_size);
   }

   static void readCallback(uv_stream_t *stream, ssize_t nread, uv_buf_t buf)
   {
   // TODO(bob): Implement me!
   printf("Read %ld bytes\n", nread);
   }
   */

  static void readBytesCallback(uv_fs_t *request)
  {
    // TODO(bob): Handle errors!
    FSReadTask* task = reinterpret_cast<FSReadTask*>(request->data);

    gc<Object> result = task->buffer();
    if (request->result != 0)
    {
      // Trim the buffer to the actually read size.
      task->buffer()->truncate(request->result);
    }
    else
    {
      // If we read when at EOF, return done.
      result = task->fiber()->vm().getBuiltIn(BUILT_IN_DONE);
    }

    task->complete(result);
  }

  void FileObject::readBytes(gc<Fiber> fiber, int size)
  {
    FSReadTask* task = new FSReadTask(fiber, size);

    // TODO(bob): Check result.
    uv_fs_read(task->loop(), task->request(), file_,
               task->buffer()->data(), task->buffer()->count(), -1,
               readBytesCallback);

    // TODO(bob): Use this for the streaming methods:
    /*
     // TODO(bob): What if you call read on the same file multiple times?
     // Should the pipe be reused?
     // Get a pipe to the file.
     uv_pipe_t* pipe = tasks_.createPipe(fiber);
     uv_pipe_init(loop_, pipe, 0);
     uv_pipe_open(pipe, file->file());

     // TODO(bob): Check result.
     uv_read_start(reinterpret_cast<uv_stream_t*>(pipe), allocateCallback,
     readCallback);
     */
  }

  static void closeFileCallback(uv_fs_t* handle)
  {
    Task* task = static_cast<Task*>(handle->data);

    // Close returns nothing.
    task->complete(NULL);
  }

  void FileObject::close(gc<Fiber> fiber)
  {
    ASSERT(isOpen_, "IO library should not call close on a closed file.");
    // Mark the file closed immediately so other fibers can't try to use it.
    isOpen_ = false;

    FSTask* task = new FSTask(fiber);
    uv_fs_close(task->loop(), task->request(), file_,
                closeFileCallback);
  }

  gc<ClassObject> FileObject::getClass(VM& vm) const
  {
    return vm.fileClass();
  }

  gc<String> FileObject::toString() const
  {
    // TODO(bob): Include some kind of ID or something here.
    return String::create("[file]");
  }

  void FileObject::reach()
  {
    // TODO(bob): How should we handle file_ here?
  }

  gc<ClassObject> StreamObject::getClass(VM& vm) const
  {
    return vm.streamClass();
  }

  gc<String> StreamObject::toString() const
  {
    // TODO(bob): Include some kind of ID or something here.
    return String::create("[stream]");
  }
}
<|endoftext|>


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

#include <benchmark/benchmark.h>
#include <grpc/grpc.h>

#include <condition_variable>
#include <mutex>

#include "src/core/lib/iomgr/executor/threadpool.h"
#include "test/cpp/microbenchmarks/helpers.h"
#include "test/cpp/util/test_config.h"

namespace grpc {
namespace testing {

// This helper class allows a thread to block for a pre-specified number of
// actions. BlockingCounter has an initial non-negative count on initialization.
// Each call to DecrementCount will decrease the count by 1. When making a call
// to Wait, if the count is greater than 0, the thread will be blocked, until
// the count reaches 0.
class BlockingCounter {
 public:
  BlockingCounter(int count) : count_(count) {}
  void DecrementCount() {
    std::lock_guard<std::mutex> l(mu_);
    count_--;
    if (count_ == 0) cv_.notify_all();
  }

  void Wait() {
    std::unique_lock<std::mutex> l(mu_);
    while (count_ > 0) {
      cv_.wait(l);
    }
  }

 private:
  int count_;
  std::mutex mu_;
  std::condition_variable cv_;
};

// This is a functor/closure class for threadpool microbenchmark.
// This functor (closure) class will add another functor into pool if the
// number passed in (num_add) is greater than 0. Otherwise, it will decrement
// the counter to indicate that task is finished. This functor will suicide at
// the end, therefore, no need for caller to do clean-ups.
class AddAnotherFunctor : public grpc_experimental_completion_queue_functor {
 public:
  AddAnotherFunctor(grpc_core::ThreadPool* pool, BlockingCounter* counter,
                    int num_add)
      : pool_(pool), counter_(counter), num_add_(num_add) {
    functor_run = &AddAnotherFunctor::Run;
    internal_next = this;
    internal_success = 0;
  }
  // When the functor gets to run in thread pool, it will take itself as first
  // argument and internal_success as second one.
  static void Run(grpc_experimental_completion_queue_functor* cb, int ok) {
    auto* callback = static_cast<AddAnotherFunctor*>(cb);
    if (--callback->num_add_ > 0) {
      callback->pool_->Add(new AddAnotherFunctor(
          callback->pool_, callback->counter_, callback->num_add_));
    } else {
      callback->counter_->DecrementCount();
    }
    // Suicides.
    delete callback;
  }

 private:
  grpc_core::ThreadPool* pool_;
  BlockingCounter* counter_;
  int num_add_;
};

void ThreadPoolAddAnotherHelper(benchmark::State& state,
                                int concurrent_functor) {
  const int num_iterations = state.range(0);
  const int num_threads = state.range(1);
  // Number of adds done by each closure.
  const int num_add = num_iterations / concurrent_functor;
  grpc_core::ThreadPool pool(num_threads);
  while (state.KeepRunningBatch(num_iterations)) {
    BlockingCounter counter(concurrent_functor);
    for (int i = 0; i < concurrent_functor; ++i) {
      pool.Add(new AddAnotherFunctor(&pool, &counter, num_add));
    }
    counter.Wait();
  }
  state.SetItemsProcessed(state.iterations());
}

static void BM_ThreadPool1AddAnother(benchmark::State& state) {
  ThreadPoolAddAnotherHelper(state, 1);
}
// First pair is range for number of iterations (num_iterations).
// Second pair is range for thread pool size (num_threads).
BENCHMARK(BM_ThreadPool1AddAnother)->RangePair(524288, 524288, 1, 1024);

static void BM_ThreadPool4AddAnother(benchmark::State& state) {
  ThreadPoolAddAnotherHelper(state, 4);
}
BENCHMARK(BM_ThreadPool4AddAnother)->RangePair(524288, 524288, 1, 1024);

static void BM_ThreadPool8AddAnother(benchmark::State& state) {
  ThreadPoolAddAnotherHelper(state, 8);
}
BENCHMARK(BM_ThreadPool8AddAnother)->RangePair(524288, 524288, 1, 1024);

static void BM_ThreadPool16AddAnother(benchmark::State& state) {
  ThreadPoolAddAnotherHelper(state, 16);
}
BENCHMARK(BM_ThreadPool16AddAnother)->RangePair(524288, 524288, 1, 1024);

static void BM_ThreadPool32AddAnother(benchmark::State& state) {
  ThreadPoolAddAnotherHelper(state, 32);
}
BENCHMARK(BM_ThreadPool32AddAnother)->RangePair(524288, 524288, 1, 1024);

static void BM_ThreadPool64AddAnother(benchmark::State& state) {
  ThreadPoolAddAnotherHelper(state, 64);
}
BENCHMARK(BM_ThreadPool64AddAnother)->RangePair(524288, 524288, 1, 1024);

static void BM_ThreadPool128AddAnother(benchmark::State& state) {
  ThreadPoolAddAnotherHelper(state, 128);
}
BENCHMARK(BM_ThreadPool128AddAnother)->RangePair(524288, 524288, 1, 1024);

static void BM_ThreadPool512AddAnother(benchmark::State& state) {
  ThreadPoolAddAnotherHelper(state, 512);
}
BENCHMARK(BM_ThreadPool512AddAnother)->RangePair(524288, 524288, 1, 1024);

static void BM_ThreadPool2048AddAnother(benchmark::State& state) {
  ThreadPoolAddAnotherHelper(state, 2048);
}
BENCHMARK(BM_ThreadPool2048AddAnother)->RangePair(524288, 524288, 1, 1024);

// A functor class that will delete self on end of running.
class SuicideFunctorForAdd : public grpc_experimental_completion_queue_functor {
 public:
  SuicideFunctorForAdd(BlockingCounter* counter) : counter_(counter) {
    functor_run = &SuicideFunctorForAdd::Run;
    internal_next = this;
    internal_success = 0;
  }

  static void Run(grpc_experimental_completion_queue_functor* cb, int ok) {
    // On running, the first argument would be itself.
    auto* callback = static_cast<SuicideFunctorForAdd*>(cb);
    callback->counter_->DecrementCount();
    delete callback;
  }

 private:
  BlockingCounter* counter_;
};

// Performs the scenario of external thread(s) adding closures into pool.
static void BM_ThreadPoolExternalAdd(benchmark::State& state) {
  static grpc_core::ThreadPool* external_add_pool = nullptr;
  // Setup for each run of test.
  if (state.thread_index == 0) {
    const int num_threads = state.range(1);
    external_add_pool = grpc_core::New<grpc_core::ThreadPool>(num_threads);
  }
  const int num_iterations = state.range(0) / state.threads;
  while (state.KeepRunningBatch(num_iterations)) {
    BlockingCounter counter(num_iterations);
    for (int i = 0; i < num_iterations; ++i) {
      external_add_pool->Add(new SuicideFunctorForAdd(&counter));
    }
    counter.Wait();
  }

  // Teardown at the end of each test run.
  if (state.thread_index == 0) {
    state.SetItemsProcessed(state.range(0));
    grpc_core::Delete(external_add_pool);
  }
}
BENCHMARK(BM_ThreadPoolExternalAdd)
    // First pair is range for number of iterations (num_iterations).
    // Second pair is range for thread pool size (num_threads).
    ->RangePair(524288, 524288, 1, 1024)
    ->ThreadRange(1, 256);  // Concurrent external thread(s) up to 256

// Functor (closure) that adds itself into pool repeatedly. By adding self, the
// overhead would be low and can measure the time of add more accurately.
class AddSelfFunctor : public grpc_experimental_completion_queue_functor {
 public:
  AddSelfFunctor(grpc_core::ThreadPool* pool, BlockingCounter* counter,
                 int num_add)
      : pool_(pool), counter_(counter), num_add_(num_add) {
    functor_run = &AddSelfFunctor::Run;
    internal_next = this;
    internal_success = 0;
  }
  // When the functor gets to run in thread pool, it will take itself as first
  // argument and internal_success as second one.
  static void Run(grpc_experimental_completion_queue_functor* cb, int ok) {
    auto* callback = static_cast<AddSelfFunctor*>(cb);
    if (--callback->num_add_ > 0) {
      callback->pool_->Add(cb);
    } else {
      callback->counter_->DecrementCount();
      // Suicides.
      delete callback;
    }
  }

 private:
  grpc_core::ThreadPool* pool_;
  BlockingCounter* counter_;
  int num_add_;
};

void ThreadPoolAddSelfHelper(benchmark::State& state, int concurrent_functor) {
  const int num_iterations = state.range(0);
  const int num_threads = state.range(1);
  // Number of adds done by each closure.
  const int num_add = num_iterations / concurrent_functor;
  grpc_core::ThreadPool pool(num_threads);
  while (state.KeepRunningBatch(num_iterations)) {
    BlockingCounter counter(concurrent_functor);
    for (int i = 0; i < concurrent_functor; ++i) {
      pool.Add(new AddSelfFunctor(&pool, &counter, num_add));
    }
    counter.Wait();
  }
  state.SetItemsProcessed(state.iterations());
}

static void BM_ThreadPool1AddSelf(benchmark::State& state) {
  ThreadPoolAddSelfHelper(state, 1);
}
// First pair is range for number of iterations (num_iterations).
// Second pair is range for thread pool size (num_threads).
BENCHMARK(BM_ThreadPool1AddSelf)->RangePair(524288, 524288, 1, 1024);

static void BM_ThreadPool4AddSelf(benchmark::State& state) {
  ThreadPoolAddSelfHelper(state, 4);
}
BENCHMARK(BM_ThreadPool4AddSelf)->RangePair(524288, 524288, 1, 1024);

static void BM_ThreadPool8AddSelf(benchmark::State& state) {
  ThreadPoolAddSelfHelper(state, 8);
}
BENCHMARK(BM_ThreadPool8AddSelf)->RangePair(524288, 524288, 1, 1024);

static void BM_ThreadPool16AddSelf(benchmark::State& state) {
  ThreadPoolAddSelfHelper(state, 16);
}
BENCHMARK(BM_ThreadPool16AddSelf)->RangePair(524288, 524288, 1, 1024);

static void BM_ThreadPool32AddSelf(benchmark::State& state) {
  ThreadPoolAddSelfHelper(state, 32);
}
BENCHMARK(BM_ThreadPool32AddSelf)->RangePair(524288, 524288, 1, 1024);

static void BM_ThreadPool64AddSelf(benchmark::State& state) {
  ThreadPoolAddSelfHelper(state, 64);
}
BENCHMARK(BM_ThreadPool64AddSelf)->RangePair(524288, 524288, 1, 1024);

static void BM_ThreadPool128AddSelf(benchmark::State& state) {
  ThreadPoolAddSelfHelper(state, 128);
}
BENCHMARK(BM_ThreadPool128AddSelf)->RangePair(524288, 524288, 1, 1024);

static void BM_ThreadPool512AddSelf(benchmark::State& state) {
  ThreadPoolAddSelfHelper(state, 512);
}
BENCHMARK(BM_ThreadPool512AddSelf)->RangePair(524288, 524288, 1, 1024);

static void BM_ThreadPool2048AddSelf(benchmark::State& state) {
  ThreadPoolAddSelfHelper(state, 2048);
}
BENCHMARK(BM_ThreadPool2048AddSelf)->RangePair(524288, 524288, 1, 1024);

#if defined(__GNUC__) && !defined(SWIG)
#if defined(__i386__) || defined(__x86_64__)
#define CACHELINE_SIZE 64
#elif defined(__powerpc64__)
#define CACHELINE_SIZE 128
#elif defined(__aarch64__)
#define CACHELINE_SIZE 64
#elif defined(__arm__)
#if defined(__ARM_ARCH_5T__)
#define CACHELINE_SIZE 32
#elif defined(__ARM_ARCH_7A__)
#define CACHELINE_SIZE 64
#endif
#endif
#ifndef CACHELINE_SIZE
#define CACHELINE_SIZE 64
#endif
#endif

// A functor (closure) that simulates closures with small but non-trivial amount
// of work.
class ShortWorkFunctorForAdd
    : public grpc_experimental_completion_queue_functor {
 public:
  BlockingCounter* counter_;

  ShortWorkFunctorForAdd() {
    functor_run = &ShortWorkFunctorForAdd::Run;
    internal_next = this;
    internal_success = 0;
    val_ = 0;
  }
  static void Run(grpc_experimental_completion_queue_functor* cb, int ok) {
    auto* callback = static_cast<ShortWorkFunctorForAdd*>(cb);
    // Uses pad to avoid compiler complaining unused variable error.
    callback->pad[0] = 0;
    for (int i = 0; i < 1000; ++i) {
      callback->val_++;
    }
    callback->counter_->DecrementCount();
  }

 private:
  char pad[CACHELINE_SIZE];
  volatile int val_;
};

// Simulates workloads where many short running callbacks are added to the
// threadpool. The callbacks are not enough to keep all the workers busy
// continuously so the number of workers running changes overtime.
//
// In effect this tests how well the threadpool avoids spurious wakeups.
static void BM_SpikyLoad(benchmark::State& state) {
  const int num_threads = state.range(0);

  const int kNumSpikes = 1000;
  const int batch_size = 3 * num_threads;
  std::vector<ShortWorkFunctorForAdd> work_vector(batch_size);
  while (state.KeepRunningBatch(kNumSpikes * batch_size)) {
    grpc_core::ThreadPool pool(num_threads);
    for (int i = 0; i != kNumSpikes; ++i) {
      BlockingCounter counter(batch_size);
      for (auto& w : work_vector) {
        w.counter_ = &counter;
        pool.Add(&w);
      }
      counter.Wait();
    }
  }
  state.SetItemsProcessed(state.iterations() * batch_size);
}
BENCHMARK(BM_SpikyLoad)->Arg(1)->Arg(2)->Arg(4)->Arg(8)->Arg(16);

}  // namespace testing
}  // namespace grpc

// Some distros have RunSpecifiedBenchmarks under the benchmark namespace,
// and others do not. This allows us to support both modes.
namespace benchmark {
void RunTheBenchmarksNamespaced() { RunSpecifiedBenchmarks(); }
}  // namespace benchmark

int main(int argc, char* argv[]) {
  LibraryInitializer libInit;
  ::benchmark::Initialize(&argc, argv);
  ::grpc::testing::InitTest(&argc, &argv, false);
  benchmark::RunTheBenchmarksNamespaced();
  return 0;
}
<commit_msg>Use Template<commit_after>/*
 *
 * Copyright 2019 gRPC authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

#include <benchmark/benchmark.h>
#include <grpc/grpc.h>

#include <condition_variable>
#include <mutex>

#include "src/core/lib/iomgr/executor/threadpool.h"
#include "test/cpp/microbenchmarks/helpers.h"
#include "test/cpp/util/test_config.h"

namespace grpc {
namespace testing {

// This helper class allows a thread to block for a pre-specified number of
// actions. BlockingCounter has an initial non-negative count on initialization.
// Each call to DecrementCount will decrease the count by 1. When making a call
// to Wait, if the count is greater than 0, the thread will be blocked, until
// the count reaches 0.
class BlockingCounter {
 public:
  BlockingCounter(int count) : count_(count) {}
  void DecrementCount() {
    std::lock_guard<std::mutex> l(mu_);
    count_--;
    if (count_ == 0) cv_.notify_all();
  }

  void Wait() {
    std::unique_lock<std::mutex> l(mu_);
    while (count_ > 0) {
      cv_.wait(l);
    }
  }

 private:
  int count_;
  std::mutex mu_;
  std::condition_variable cv_;
};

// This is a functor/closure class for threadpool microbenchmark.
// This functor (closure) class will add another functor into pool if the
// number passed in (num_add) is greater than 0. Otherwise, it will decrement
// the counter to indicate that task is finished. This functor will suicide at
// the end, therefore, no need for caller to do clean-ups.
class AddAnotherFunctor : public grpc_experimental_completion_queue_functor {
 public:
  AddAnotherFunctor(grpc_core::ThreadPool* pool, BlockingCounter* counter,
                    int num_add)
      : pool_(pool), counter_(counter), num_add_(num_add) {
    functor_run = &AddAnotherFunctor::Run;
    internal_next = this;
    internal_success = 0;
  }
  // When the functor gets to run in thread pool, it will take itself as first
  // argument and internal_success as second one.
  static void Run(grpc_experimental_completion_queue_functor* cb, int ok) {
    auto* callback = static_cast<AddAnotherFunctor*>(cb);
    if (--callback->num_add_ > 0) {
      callback->pool_->Add(new AddAnotherFunctor(
          callback->pool_, callback->counter_, callback->num_add_));
    } else {
      callback->counter_->DecrementCount();
    }
    // Suicides.
    delete callback;
  }

 private:
  grpc_core::ThreadPool* pool_;
  BlockingCounter* counter_;
  int num_add_;
};

template <int kConcurrentFunctor>
static void ThreadPoolAddAnother(benchmark::State& state) {
  const int num_iterations = state.range(0);
  const int num_threads = state.range(1);
  // Number of adds done by each closure.
  const int num_add = num_iterations / kConcurrentFunctor;
  grpc_core::ThreadPool pool(num_threads);
  while (state.KeepRunningBatch(num_iterations)) {
    BlockingCounter counter(kConcurrentFunctor);
    for (int i = 0; i < kConcurrentFunctor; ++i) {
      pool.Add(new AddAnotherFunctor(&pool, &counter, num_add));
    }
    counter.Wait();
  }
  state.SetItemsProcessed(state.iterations());
}

// First pair of arguments is range for number of iterations (num_iterations).
// Second pair of arguments is range for thread pool size (num_threads).
BENCHMARK_TEMPLATE(ThreadPoolAddAnother, 1)->RangePair(524288, 524288, 1, 1024);
BENCHMARK_TEMPLATE(ThreadPoolAddAnother, 4)->RangePair(524288, 524288, 1, 1024);
BENCHMARK_TEMPLATE(ThreadPoolAddAnother, 8)->RangePair(524288, 524288, 1, 1024);
BENCHMARK_TEMPLATE(ThreadPoolAddAnother, 16)
    ->RangePair(524288, 524288, 1, 1024);
BENCHMARK_TEMPLATE(ThreadPoolAddAnother, 32)
    ->RangePair(524288, 524288, 1, 1024);
BENCHMARK_TEMPLATE(ThreadPoolAddAnother, 64)
    ->RangePair(524288, 524288, 1, 1024);
BENCHMARK_TEMPLATE(ThreadPoolAddAnother, 128)
    ->RangePair(524288, 524288, 1, 1024);
BENCHMARK_TEMPLATE(ThreadPoolAddAnother, 512)
    ->RangePair(524288, 524288, 1, 1024);
BENCHMARK_TEMPLATE(ThreadPoolAddAnother, 2048)
    ->RangePair(524288, 524288, 1, 1024);

// A functor class that will delete self on end of running.
class SuicideFunctorForAdd : public grpc_experimental_completion_queue_functor {
 public:
  SuicideFunctorForAdd(BlockingCounter* counter) : counter_(counter) {
    functor_run = &SuicideFunctorForAdd::Run;
    internal_next = this;
    internal_success = 0;
  }

  static void Run(grpc_experimental_completion_queue_functor* cb, int ok) {
    // On running, the first argument would be itself.
    auto* callback = static_cast<SuicideFunctorForAdd*>(cb);
    callback->counter_->DecrementCount();
    delete callback;
  }

 private:
  BlockingCounter* counter_;
};

// Performs the scenario of external thread(s) adding closures into pool.
static void BM_ThreadPoolExternalAdd(benchmark::State& state) {
  static grpc_core::ThreadPool* external_add_pool = nullptr;
  // Setup for each run of test.
  if (state.thread_index == 0) {
    const int num_threads = state.range(1);
    external_add_pool = grpc_core::New<grpc_core::ThreadPool>(num_threads);
  }
  const int num_iterations = state.range(0) / state.threads;
  while (state.KeepRunningBatch(num_iterations)) {
    BlockingCounter counter(num_iterations);
    for (int i = 0; i < num_iterations; ++i) {
      external_add_pool->Add(new SuicideFunctorForAdd(&counter));
    }
    counter.Wait();
  }

  // Teardown at the end of each test run.
  if (state.thread_index == 0) {
    state.SetItemsProcessed(state.range(0));
    grpc_core::Delete(external_add_pool);
  }
}
BENCHMARK(BM_ThreadPoolExternalAdd)
    // First pair is range for number of iterations (num_iterations).
    // Second pair is range for thread pool size (num_threads).
    ->RangePair(524288, 524288, 1, 1024)
    ->ThreadRange(1, 256);  // Concurrent external thread(s) up to 256

// Functor (closure) that adds itself into pool repeatedly. By adding self, the
// overhead would be low and can measure the time of add more accurately.
class AddSelfFunctor : public grpc_experimental_completion_queue_functor {
 public:
  AddSelfFunctor(grpc_core::ThreadPool* pool, BlockingCounter* counter,
                 int num_add)
      : pool_(pool), counter_(counter), num_add_(num_add) {
    functor_run = &AddSelfFunctor::Run;
    internal_next = this;
    internal_success = 0;
  }
  // When the functor gets to run in thread pool, it will take itself as first
  // argument and internal_success as second one.
  static void Run(grpc_experimental_completion_queue_functor* cb, int ok) {
    auto* callback = static_cast<AddSelfFunctor*>(cb);
    if (--callback->num_add_ > 0) {
      callback->pool_->Add(cb);
    } else {
      callback->counter_->DecrementCount();
      // Suicides.
      delete callback;
    }
  }

 private:
  grpc_core::ThreadPool* pool_;
  BlockingCounter* counter_;
  int num_add_;
};

template <int kConcurrentFunctor>
static void ThreadPoolAddSelf(benchmark::State& state) {
  const int num_iterations = state.range(0);
  const int num_threads = state.range(1);
  // Number of adds done by each closure.
  const int num_add = num_iterations / kConcurrentFunctor;
  grpc_core::ThreadPool pool(num_threads);
  while (state.KeepRunningBatch(num_iterations)) {
    BlockingCounter counter(kConcurrentFunctor);
    for (int i = 0; i < kConcurrentFunctor; ++i) {
      pool.Add(new AddSelfFunctor(&pool, &counter, num_add));
    }
    counter.Wait();
  }
  state.SetItemsProcessed(state.iterations());
}

// First pair of arguments is range for number of iterations (num_iterations).
// Second pair of arguments is range for thread pool size (num_threads).
BENCHMARK_TEMPLATE(ThreadPoolAddSelf, 1)->RangePair(524288, 524288, 1, 1024);
BENCHMARK_TEMPLATE(ThreadPoolAddSelf, 4)->RangePair(524288, 524288, 1, 1024);
BENCHMARK_TEMPLATE(ThreadPoolAddSelf, 8)->RangePair(524288, 524288, 1, 1024);
BENCHMARK_TEMPLATE(ThreadPoolAddSelf, 16)->RangePair(524288, 524288, 1, 1024);
BENCHMARK_TEMPLATE(ThreadPoolAddSelf, 32)->RangePair(524288, 524288, 1, 1024);
BENCHMARK_TEMPLATE(ThreadPoolAddSelf, 64)->RangePair(524288, 524288, 1, 1024);
BENCHMARK_TEMPLATE(ThreadPoolAddSelf, 128)->RangePair(524288, 524288, 1, 1024);
BENCHMARK_TEMPLATE(ThreadPoolAddSelf, 512)->RangePair(524288, 524288, 1, 1024);
BENCHMARK_TEMPLATE(ThreadPoolAddSelf, 2048)->RangePair(524288, 524288, 1, 1024);

#if defined(__GNUC__) && !defined(SWIG)
#if defined(__i386__) || defined(__x86_64__)
#define CACHELINE_SIZE 64
#elif defined(__powerpc64__)
#define CACHELINE_SIZE 128
#elif defined(__aarch64__)
#define CACHELINE_SIZE 64
#elif defined(__arm__)
#if defined(__ARM_ARCH_5T__)
#define CACHELINE_SIZE 32
#elif defined(__ARM_ARCH_7A__)
#define CACHELINE_SIZE 64
#endif
#endif
#ifndef CACHELINE_SIZE
#define CACHELINE_SIZE 64
#endif
#endif

// A functor (closure) that simulates closures with small but non-trivial amount
// of work.
class ShortWorkFunctorForAdd
    : public grpc_experimental_completion_queue_functor {
 public:
  BlockingCounter* counter_;

  ShortWorkFunctorForAdd() {
    functor_run = &ShortWorkFunctorForAdd::Run;
    internal_next = this;
    internal_success = 0;
    val_ = 0;
  }
  static void Run(grpc_experimental_completion_queue_functor* cb, int ok) {
    auto* callback = static_cast<ShortWorkFunctorForAdd*>(cb);
    // Uses pad to avoid compiler complaining unused variable error.
    callback->pad[0] = 0;
    for (int i = 0; i < 1000; ++i) {
      callback->val_++;
    }
    callback->counter_->DecrementCount();
  }

 private:
  char pad[CACHELINE_SIZE];
  volatile int val_;
};

// Simulates workloads where many short running callbacks are added to the
// threadpool. The callbacks are not enough to keep all the workers busy
// continuously so the number of workers running changes overtime.
//
// In effect this tests how well the threadpool avoids spurious wakeups.
static void BM_SpikyLoad(benchmark::State& state) {
  const int num_threads = state.range(0);

  const int kNumSpikes = 1000;
  const int batch_size = 3 * num_threads;
  std::vector<ShortWorkFunctorForAdd> work_vector(batch_size);
  while (state.KeepRunningBatch(kNumSpikes * batch_size)) {
    grpc_core::ThreadPool pool(num_threads);
    for (int i = 0; i != kNumSpikes; ++i) {
      BlockingCounter counter(batch_size);
      for (auto& w : work_vector) {
        w.counter_ = &counter;
        pool.Add(&w);
      }
      counter.Wait();
    }
  }
  state.SetItemsProcessed(state.iterations() * batch_size);
}
BENCHMARK(BM_SpikyLoad)->Arg(1)->Arg(2)->Arg(4)->Arg(8)->Arg(16);

}  // namespace testing
}  // namespace grpc

// Some distros have RunSpecifiedBenchmarks under the benchmark namespace,
// and others do not. This allows us to support both modes.
namespace benchmark {
void RunTheBenchmarksNamespaced() { RunSpecifiedBenchmarks(); }
}  // namespace benchmark

int main(int argc, char* argv[]) {
  LibraryInitializer libInit;
  ::benchmark::Initialize(&argc, argv);
  ::grpc::testing::InitTest(&argc, &argv, false);
  benchmark::RunTheBenchmarksNamespaced();
  return 0;
}
<|endoftext|>


<commit_before><commit_msg>remove depends on set container<commit_after><|endoftext|>


<commit_before>#pragma once
#include <vector>

#include "depthai-shared/common/CameraBoardSocket.hpp"
#include "depthai-shared/common/CameraInfo.hpp"
#include "depthai-shared/common/Extrinsics.hpp"
#include "depthai-shared/common/Point3f.hpp"
#include "depthai-shared/common/StereoRectification.hpp"

// libraries
#include "nlohmann/json.hpp"

namespace dai {
/**
 * EepromData structure
 *
 * Contains the Calibration and Board data stored on device
 */
struct EepromData {
    uint32_t version = 0;
    bool swapLeftRightCam = false;
    std::string boardName, boardRev;
    std::unordered_map<CameraBoardSocket, CameraInfo> cameraData;
    StereoRectification stereoRectificationData;
    Extrinsics imuExtrinsics;
    // TODO(sachin): Do I need to add something for IR projector
    NLOHMANN_DEFINE_TYPE_INTRUSIVE(EepromData, version, swapLeftRightCam, boardName, boardRev, cameraData, stereoRectificationData, imuExtrinsics);
};

}  // namespace dai
<commit_msg>Added some headers file<commit_after>#pragma once
#include <string>
#include <unordered_map>
#include <vector>

#include "depthai-shared/common/CameraBoardSocket.hpp"
#include "depthai-shared/common/CameraInfo.hpp"
#include "depthai-shared/common/Extrinsics.hpp"
#include "depthai-shared/common/Point3f.hpp"
#include "depthai-shared/common/StereoRectification.hpp"

// libraries
#include "nlohmann/json.hpp"

namespace dai {
/**
 * EepromData structure
 *
 * Contains the Calibration and Board data stored on device
 */
struct EepromData {
    uint32_t version = 0;
    bool swapLeftRightCam = false;
    std::string boardName, boardRev;
    std::unordered_map<CameraBoardSocket, CameraInfo> cameraData;
    StereoRectification stereoRectificationData;
    Extrinsics imuExtrinsics;
    // TODO(sachin): Do I need to add something for IR projector
    NLOHMANN_DEFINE_TYPE_INTRUSIVE(EepromData, version, swapLeftRightCam, boardName, boardRev, cameraData, stereoRectificationData, imuExtrinsics);
};

}  // namespace dai
<|endoftext|>


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

#include <print.hpp>
#include <primecount-internal.hpp>
#include <int128.hpp>
#include <stdint.h>

#include <iostream>
#include <iomanip>
#include <string>

using namespace std;

namespace {

bool print_status_ = false;

bool print_variables_ = false;

}

namespace primecount {

void set_print_status(bool print_status)
{
#ifdef HAVE_MPI
  print_status_ = print_status && is_mpi_master_proc();
#else
  print_status_ = print_status;
#endif
}

void set_print_variables(bool print_variables)
{
#ifdef HAVE_MPI
  print_variables_ = print_variables && is_mpi_master_proc();
#else
  print_variables_ = print_variables;
#endif
}

bool print_result()
{
#ifdef HAVE_MPI
  return !print_variables() && is_mpi_master_proc();
#else
  return !print_variables();
#endif
}

void print_threads(int threads)
{
#ifdef HAVE_MPI
  cout << "processes = " << mpi_num_procs() << endl;
  cout << "threads = " << mpi_num_procs() << " * " << validate_threads(threads) << endl;
#else
  cout << "threads = " << validate_threads(threads) << endl;
#endif
}

bool print_status()
{
  return print_status_;
}

bool print_variables()
{
  return print_variables_;
}

void print(const string& str)
{
  if (print_status())
    cout << str << endl;
}

void print(maxint_t x, int64_t y, int64_t z, int64_t c, double alpha, int threads)
{
  if (print_variables())
  {
    cout << "x = " << x << endl;
    cout << "y = " << y << endl;
    cout << "z = " << z << endl;
    cout << "c = " << c << endl;
    cout << "alpha = " << fixed << setprecision(3) << alpha << endl;
    print_threads(threads);
  }
}

void print(maxint_t x, int64_t y, int threads)
{
  if (print_variables())
  {
    maxint_t z = x / y;
    cout << "x = " << x << endl;
    cout << "y = " << y << endl;
    cout << "z = " << z << endl;
    cout << "alpha = " << fixed << setprecision(3) << get_alpha(x, y) << endl;
    print_threads(threads);
    cout << endl;
  }
}

void print(maxint_t x, int64_t y, int64_t c, int threads)
{
  if (print_variables())
  {
    maxint_t z = x / y;
    cout << "x = " << x << endl;
    cout << "y = " << y << endl;
    cout << "z = " << z << endl;
    cout << "c = " << c << endl;
    cout << "alpha = " << fixed << setprecision(3) << get_alpha(x, y) << endl;
    print_threads(threads);
    cout << endl;
  }
}

void print(const string& res_str, maxint_t res, double time)
{
  if (print_status())
  {
    cout << "\r" << string(50,' ') << "\r";
    cout << "Status: 100%" << endl;
    cout << res_str << " = " << res << endl;
    print_seconds(get_wtime() - time);
  }
}

void print_seconds(double seconds)
{
  cout << "Seconds: " << fixed << setprecision(3) << seconds << endl;
}

} // namespace
<commit_msg>Fix printing variables<commit_after>///
/// @file  print.cpp
///
/// Copyright (C) 2016 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#include <print.hpp>
#include <primecount-internal.hpp>
#include <int128.hpp>
#include <stdint.h>

#include <iostream>
#include <iomanip>
#include <string>

using namespace std;

namespace {

bool print_status_ = false;

bool print_variables_ = false;

}

namespace primecount {

void set_print_status(bool print_status)
{
#ifdef HAVE_MPI
  print_status_ = print_status && is_mpi_master_proc();
#else
  print_status_ = print_status;
#endif
}

void set_print_variables(bool print_variables)
{
#ifdef HAVE_MPI
  print_variables_ = print_variables && is_mpi_master_proc();
#else
  print_variables_ = print_variables;
#endif
}

bool print_result()
{
#ifdef HAVE_MPI
  return !print_variables() && is_mpi_master_proc();
#else
  return !print_variables();
#endif
}

void print_threads(int threads)
{
#ifdef HAVE_MPI
  cout << "processes = " << mpi_num_procs() << endl;
  cout << "threads = " << mpi_num_procs() << " * " << validate_threads(threads) << endl;
#else
  cout << "threads = " << validate_threads(threads) << endl;
#endif
}

bool print_status()
{
  return print_status_;
}

bool print_variables()
{
  return print_variables_;
}

void print(const string& str)
{
  if (print_status())
    cout << str << endl;
}

void print(maxint_t x, int64_t y, int64_t z, int64_t c, double alpha, int threads)
{
  if (print_status())
  {
    cout << "x = " << x << endl;
    cout << "y = " << y << endl;
    cout << "z = " << z << endl;
    cout << "c = " << c << endl;
    cout << "alpha = " << fixed << setprecision(3) << alpha << endl;
    print_threads(threads);
  }
}

void print(maxint_t x, int64_t y, int threads)
{
  if (print_variables())
  {
    maxint_t z = x / y;
    cout << "x = " << x << endl;
    cout << "y = " << y << endl;
    cout << "z = " << z << endl;
    cout << "alpha = " << fixed << setprecision(3) << get_alpha(x, y) << endl;
    print_threads(threads);
    cout << endl;
  }
}

void print(maxint_t x, int64_t y, int64_t c, int threads)
{
  if (print_variables())
  {
    maxint_t z = x / y;
    cout << "x = " << x << endl;
    cout << "y = " << y << endl;
    cout << "z = " << z << endl;
    cout << "c = " << c << endl;
    cout << "alpha = " << fixed << setprecision(3) << get_alpha(x, y) << endl;
    print_threads(threads);
    cout << endl;
  }
}

void print(const string& res_str, maxint_t res, double time)
{
  if (print_status())
  {
    cout << "\r" << string(50,' ') << "\r";
    cout << "Status: 100%" << endl;
    cout << res_str << " = " << res << endl;
    print_seconds(get_wtime() - time);
  }
}

void print_seconds(double seconds)
{
  cout << "Seconds: " << fixed << setprecision(3) << seconds << endl;
}

} // namespace
<|endoftext|>


<commit_before>#ifndef OPENGM_PARAMETERS
#define OPENGM_PARAMETERS

namespace opengm{

   template<class T,class I>
   class Parameters{
   public:
      typedef T ValueType;
      typedef I IndexType;

      Parameters(const IndexType numberOfParameters=0)
      : params_(numberOfParameters){

      }

      ValueType getParameter(const size_t pi)const{
         OPENGM_ASSERT_OP(pi,<,params_.size());
         return params_[pi];
      }

      ValueType setParameter(const size_t pi,const ValueType value){
         OPENGM_ASSERT_OP(pi,<,params_.size());
         params_[pi]=value;
      }

      ValueType operator[](const size_t pi)const{
         return getParameter(pi);
      }

      size_t numberOfParameters()const{
         return params_.size();
      }

   private:

      std::vector<ValueType> params_;
   };
}

#endif /* OPENGM_PARAMETERS */<commit_msg>fix bug in parameters<commit_after>#ifndef OPENGM_PARAMETERS
#define OPENGM_PARAMETERS

namespace opengm{

   template<class T,class I>
   class Parameters{
   public:
      typedef T ValueType;
      typedef I IndexType;

      Parameters(const IndexType numberOfParameters=0)
      : params_(numberOfParameters){

      }

      ValueType getParameter(const size_t pi)const{
         OPENGM_ASSERT_OP(pi,<,params_.size());
         return params_[pi];
      }

      void setParameter(const size_t pi,const ValueType value){
         OPENGM_ASSERT_OP(pi,<,params_.size());
         params_[pi]=value;
      }

      ValueType operator[](const size_t pi)const{
         return getParameter(pi);
      }

      size_t numberOfParameters()const{
         return params_.size();
      }

   private:

      std::vector<ValueType> params_;
   };
}

#endif /* OPENGM_PARAMETERS */<|endoftext|>


<commit_before>#include "Halide.h"
#include <tiramisu/utils.h>
#include <cstdlib>
#include <iostream>
#include "mkl_cblas.h"

#include "sgemm_wrapper.h"
#include "benchmarks.h"

#ifdef __cplusplus
extern "C" {
#endif

#ifdef __cplusplus
}  // extern "C"
#endif

int main(int, char **)
{
    std::vector<std::chrono::duration<double,std::milli>> duration_vector_1;
    std::vector<std::chrono::duration<double,std::milli>> duration_vector_2;

float a = 3, b = 3;

#if 1
    bool run_mkl = false;
    bool run_tiramisu = false;

    const char* env_mkl = std::getenv("RUN_REF");
    if ((env_mkl != NULL) && (env_mkl[0] == '1'))
	run_mkl = true;
    const char* env_tira = std::getenv("RUN_TIRAMISU");
    if ((env_tira != NULL) && (env_tira[0] == '1'))
	run_tiramisu = true;
#else
    bool run_mkl = true;
    bool run_tiramisu = true;
#endif

	int sizes[27][4], D = 1060 * 1060;

	/************ SIZE_IS_MULTIPLE_OF_TILE 1 ******************/

	sizes[0][0] = 4096;
	sizes[0][1] = 4096;
	sizes[0][2] = 4096;
	sizes[0][3] = 65536 * 4096;

	sizes[1][0] = 128;
	sizes[1][1] = 128;
	sizes[1][2] = 128;
	sizes[1][3] = 128;

	sizes[2][0] = 512;
	sizes[2][1] = 512;
	sizes[2][2] = 512;
	sizes[2][3] = 1024;

	sizes[3][0] = 1024;
	sizes[3][1] = 1024;
	sizes[3][2] = 1024;
	sizes[3][3] = 1024 * 1024;

	sizes[4][0] = 128;
	sizes[4][1] = 128;
	sizes[4][2] = 256;
	sizes[4][3] = D;

	sizes[5][0] = 2048;
	sizes[5][1] = 2048;
	sizes[5][2] = 2048;
	sizes[5][3] = D;

	sizes[6][0] = 2048;
	sizes[6][1] = 2048;
	sizes[6][2] = 1024;
	sizes[6][3] = D;

	sizes[7][0] = 1024;
	sizes[7][1] = 1024;
	sizes[7][2] = 2048;
	sizes[7][3] = D;

	sizes[8][0] = 1024;
	sizes[8][1] = 1024;
	sizes[8][2] = 512;
	sizes[8][3] = D;

	sizes[9][0] = 512;
	sizes[9][1] = 512;
	sizes[9][2] = 1024;
	sizes[9][3] = D;

	sizes[10][0] = 512;
	sizes[10][1] = 512;
	sizes[10][2] = 256;
	sizes[10][3] = D;

	sizes[11][0] = 128;
	sizes[11][1] = 128;
	sizes[11][2] = 2048;
	sizes[11][3] = D;

	sizes[12][0] = 256;
	sizes[12][1] = 256;
	sizes[12][2] = 256;
	sizes[12][3] = D;

	sizes[13][0] = 128;
	sizes[13][1] = 128;
	sizes[13][2] = 512;
	sizes[13][3] = D;

	sizes[14][0] = 128;
	sizes[14][1] = 128;
	sizes[14][2] = 1024;
	sizes[14][3] = D;

	sizes[15][0] = 128;
	sizes[15][1] = 128;
	sizes[15][2] = 64;
	sizes[15][3] = D;

	/**************  SIZE_IS_MULTIPLE_OF_TILE 0  ****************/

	sizes[16][0] = 1060;
	sizes[16][1] = 1060;
	sizes[16][2] = 1060;
	sizes[16][3] = D;

	sizes[17][0] = 4;
	sizes[17][1] = 4;
	sizes[17][2] = 4;
	sizes[17][3] = D;

	sizes[18][0] = 8;
	sizes[18][1] = 8;
	sizes[18][2] = 4;
	sizes[18][3] = D;

	sizes[19][0] = 16;
	sizes[19][1] = 16;
	sizes[19][2] = 4;
	sizes[19][3] = D;

	sizes[20][0] = 16;
	sizes[20][1] = 16;
	sizes[20][2] = 16;
	sizes[20][3] = D;

	sizes[21][0] = 8;
	sizes[21][1] = 8;
	sizes[21][2] = 16;
	sizes[21][3] = D;

	int p, q;

	if (SIZE_IS_MULTIPLE_OF_TILE)
	{
		p = 1;
		q = 16;
	}
	else
	{
		p = 16;
		q = 22;
	}

	for (int j = p; j < q; j++)
	{

		int local_N = sizes[j][0];
		int local_M = sizes[j][1];
		int local_K = sizes[j][2];
		int local_size = sizes[j][3];

		Halide::Buffer<int> SIZES(3, "SIZES");
		Halide::Buffer<float> alpha(1, "alpha");
		Halide::Buffer<float> beta(1, "beta");
		Halide::Buffer<float> A(local_N, local_K, "A");
		Halide::Buffer<float> B(local_K, local_M, "B");
		Halide::Buffer<float> C(local_N, local_M, "C");
		Halide::Buffer<float> C_mkl(local_N, local_M, "C_mkl");

		SIZES(0) = local_N; SIZES(1) = local_M; SIZES(2) = local_K;
		alpha(0) = a; beta(0) = b;
		init_buffer(A, (float)1);
		init_buffer(B, (float)1);
		init_buffer(C, (float)1);
		init_buffer(C_mkl, (float)1);

		// Calling MKL
		{
			long long int   lda, ldb, ldc;
			long long int   rmaxa, cmaxa, rmaxb, cmaxb, rmaxc, cmaxc;
			CBLAS_LAYOUT    layout = CblasRowMajor;
			CBLAS_TRANSPOSE transA = CblasNoTrans, transB = CblasNoTrans;
			long long int ma, na, mb, nb;

			if( transA == CblasNoTrans ) {
				rmaxa = local_M + 1;
				cmaxa = local_K;
				ma    = local_M;
				na    = local_K;
			} else {
				rmaxa = local_K + 1;
				cmaxa = local_M;
				ma    = local_K;
				na    = local_M;
			}
			if( transB == CblasNoTrans ) {
				rmaxb = local_K + 1;
				cmaxb = local_N;
				mb    = local_K;
				nb    = local_N;
			} else {
				rmaxb = local_N + 1;
				cmaxb = local_K;
				mb    = local_N;
				nb    = local_K;
			}
			rmaxc = local_M + 1;
			cmaxc = local_N;
			if (layout == CblasRowMajor) {
				lda=cmaxa;
				ldb=cmaxb;
				ldc=cmaxc;
			} else {
				lda=rmaxa;
				ldb=rmaxb;
				ldc=rmaxc;
			}

			for (int i = 0; i < NB_TESTS; i++)
			{
				init_buffer(C_mkl, (float)1);
				auto start1 = std::chrono::high_resolution_clock::now();
				if (run_mkl == true)
					cblas_sgemm(layout, transA, transB, local_M, local_N, local_K, a, (float *) A.raw_buffer()->host, lda, (float *) B.raw_buffer()->host, ldb, b, (float *) C_mkl.raw_buffer()->host, ldc);
				auto end1 = std::chrono::high_resolution_clock::now();
				std::chrono::duration<double,std::milli> duration1 = end1 - start1;
				duration_vector_1.push_back(duration1);
			}
		}

		for (int i = 0; i < NB_TESTS; i++)
		{
			init_buffer(C, (float)1);
			auto start2 = std::chrono::high_resolution_clock::now();
			if (run_tiramisu == true)
				sgemm_tiramisu(SIZES.raw_buffer(), alpha.raw_buffer(), beta.raw_buffer(), A.raw_buffer(), B.raw_buffer(), C.raw_buffer());
			auto end2 = std::chrono::high_resolution_clock::now();
			std::chrono::duration<double,std::milli> duration2 = end2 - start2;
			duration_vector_2.push_back(duration2);
		}

		print_time("performance_CPU.csv", "sgemm",
				{"MKL", "Tiramisu"},
				{median(duration_vector_1), median(duration_vector_2)});

		if (CHECK_CORRECTNESS)
		if (run_mkl == 1 && run_tiramisu == 1)
		{
			compare_buffers("sgemm", C, C_mkl);
			}

		if (PRINT_OUTPUT)
		{
		std::cout << "Tiramisu sgemm " << std::endl;
		print_buffer(C);
		std::cout << "MKL sgemm " << std::endl;
		print_buffer(C_mkl);
		}
	}
	return 0;
}
<commit_msg>Update sgemm_wrapper.cpp<commit_after>#include "Halide.h"
#include <tiramisu/utils.h>
#include <cstdlib>
#include <iostream>
#include "mkl_cblas.h"

#include "sgemm_wrapper.h"
#include "benchmarks.h"

#ifdef __cplusplus
extern "C" {
#endif

#ifdef __cplusplus
}  // extern "C"
#endif

int main(int, char **)
{
    std::vector<std::chrono::duration<double,std::milli>> duration_vector_1;
    std::vector<std::chrono::duration<double,std::milli>> duration_vector_2;

float a = 3, b = 3;

#if 1
    bool run_mkl = false;
    bool run_tiramisu = false;

    const char* env_mkl = std::getenv("RUN_REF");
    if ((env_mkl != NULL) && (env_mkl[0] == '1'))
	run_mkl = true;
    const char* env_tira = std::getenv("RUN_TIRAMISU");
    if ((env_tira != NULL) && (env_tira[0] == '1'))
	run_tiramisu = true;
#else
    bool run_mkl = true;
    bool run_tiramisu = true;
#endif

	int sizes[27][4], D = 1060 * 1060;

	/************ SIZE_IS_MULTIPLE_OF_TILE 1 ******************/

	sizes[0][0] = 4096;
	sizes[0][1] = 4096;
	sizes[0][2] = 4096;
	sizes[0][3] = 65536 * 4096;

	sizes[1][0] = 128;
	sizes[1][1] = 128;
	sizes[1][2] = 128;
	sizes[1][3] = 128;

	sizes[2][0] = 512;
	sizes[2][1] = 512;
	sizes[2][2] = 512;
	sizes[2][3] = 1024;

	sizes[3][0] = 1024;
	sizes[3][1] = 1024;
	sizes[3][2] = 1024;
	sizes[3][3] = 1024 * 1024;

	sizes[4][0] = 128;
	sizes[4][1] = 128;
	sizes[4][2] = 256;
	sizes[4][3] = D;

	sizes[5][0] = 2048;
	sizes[5][1] = 2048;
	sizes[5][2] = 2048;
	sizes[5][3] = D;

	sizes[6][0] = 2048;
	sizes[6][1] = 2048;
	sizes[6][2] = 1024;
	sizes[6][3] = D;

	sizes[7][0] = 1024;
	sizes[7][1] = 1024;
	sizes[7][2] = 2048;
	sizes[7][3] = D;

	sizes[8][0] = 1024;
	sizes[8][1] = 1024;
	sizes[8][2] = 512;
	sizes[8][3] = D;

	sizes[9][0] = 512;
	sizes[9][1] = 512;
	sizes[9][2] = 1024;
	sizes[9][3] = D;

	sizes[10][0] = 512;
	sizes[10][1] = 512;
	sizes[10][2] = 256;
	sizes[10][3] = D;

	sizes[11][0] = 128;
	sizes[11][1] = 128;
	sizes[11][2] = 2048;
	sizes[11][3] = D;

	sizes[12][0] = 256;
	sizes[12][1] = 256;
	sizes[12][2] = 256;
	sizes[12][3] = D;

	sizes[13][0] = 128;
	sizes[13][1] = 128;
	sizes[13][2] = 512;
	sizes[13][3] = D;

	sizes[14][0] = 128;
	sizes[14][1] = 128;
	sizes[14][2] = 1024;
	sizes[14][3] = D;

	sizes[15][0] = 128;
	sizes[15][1] = 128;
	sizes[15][2] = 64;
	sizes[15][3] = D;

	/**************  SIZE_IS_MULTIPLE_OF_TILE 0  ****************/

	sizes[16][0] = 1060;
	sizes[16][1] = 1060;
	sizes[16][2] = 1060;
	sizes[16][3] = D;

	sizes[17][0] = 4;
	sizes[17][1] = 4;
	sizes[17][2] = 4;
	sizes[17][3] = D;

	sizes[18][0] = 8;
	sizes[18][1] = 8;
	sizes[18][2] = 4;
	sizes[18][3] = D;

	sizes[19][0] = 16;
	sizes[19][1] = 16;
	sizes[19][2] = 4;
	sizes[19][3] = D;

	sizes[20][0] = 16;
	sizes[20][1] = 16;
	sizes[20][2] = 16;
	sizes[20][3] = D;

	sizes[21][0] = 8;
	sizes[21][1] = 8;
	sizes[21][2] = 16;
	sizes[21][3] = D;

	int p, q;

	if (SIZE_IS_MULTIPLE_OF_TILE)
	{
		p = 0;
		q = 16;
	}
	else
	{
		p = 16;
		q = 22;
	}

	for (int j = p; j < q; j++)
	{

	int local_N = sizes[j][0];
	int local_M = sizes[j][1];
	int local_K = sizes[j][2];
	int local_size = sizes[j][3];

	Halide::Buffer<int> SIZES(3, "SIZES");
	Halide::Buffer<float> alpha(1, "alpha");
	Halide::Buffer<float> beta(1, "beta");
	Halide::Buffer<float> A(local_N, local_K, "A");
	Halide::Buffer<float> B(local_K, local_M, "B");
	Halide::Buffer<float> C(local_N, local_M, "C");
	Halide::Buffer<float> C_mkl(local_N, local_M, "C_mkl");

	SIZES(0) = local_N; SIZES(1) = local_M; SIZES(2) = local_K;
	alpha(0) = a; beta(0) = b;
	init_buffer(A, (float)1);
	init_buffer(B, (float)1);
	init_buffer(C, (float)1);
	init_buffer(C_mkl, (float)1);

	// Calling MKL
	{
		long long int   lda, ldb, ldc;
		long long int   rmaxa, cmaxa, rmaxb, cmaxb, rmaxc, cmaxc;
		CBLAS_LAYOUT    layout = CblasRowMajor;
		CBLAS_TRANSPOSE transA = CblasNoTrans, transB = CblasNoTrans;
		long long int ma, na, mb, nb;

		if( transA == CblasNoTrans ) {
			rmaxa = local_M + 1;
			cmaxa = local_K;
			ma    = local_M;
			na    = local_K;
		} else {
			rmaxa = local_K + 1;
			cmaxa = local_M;
			ma    = local_K;
			na    = local_M;
		}
		if( transB == CblasNoTrans ) {
			rmaxb = local_K + 1;
			cmaxb = local_N;
			mb    = local_K;
			nb    = local_N;
		} else {
			rmaxb = local_N + 1;
			cmaxb = local_K;
			mb    = local_N;
			nb    = local_K;
		}
		rmaxc = local_M + 1;
		cmaxc = local_N;
		if (layout == CblasRowMajor) {
			lda=cmaxa;
			ldb=cmaxb;
			ldc=cmaxc;
		} else {
			lda=rmaxa;
			ldb=rmaxb;
			ldc=rmaxc;
		}

		for (int i = 0; i < NB_TESTS; i++)
		{
			init_buffer(C_mkl, (float)1);
			auto start1 = std::chrono::high_resolution_clock::now();
			if (run_mkl == true)
				cblas_sgemm(layout, transA, transB, local_M, local_N, local_K, a, (float *) A.raw_buffer()->host, lda, (float *) B.raw_buffer()->host, ldb, b, (float *) C_mkl.raw_buffer()->host, ldc);
			auto end1 = std::chrono::high_resolution_clock::now();
			std::chrono::duration<double,std::milli> duration1 = end1 - start1;
			duration_vector_1.push_back(duration1);
		}
	}

	for (int i = 0; i < NB_TESTS; i++)
	{
		init_buffer(C, (float)1);
		auto start2 = std::chrono::high_resolution_clock::now();
		if (run_tiramisu == true)
			sgemm_tiramisu(SIZES.raw_buffer(), alpha.raw_buffer(), beta.raw_buffer(), A.raw_buffer(), B.raw_buffer(), C.raw_buffer());
		auto end2 = std::chrono::high_resolution_clock::now();
		std::chrono::duration<double,std::milli> duration2 = end2 - start2;
		duration_vector_2.push_back(duration2);
	}

	print_time("performance_CPU.csv", "sgemm",
			{"MKL", "Tiramisu"},
			{median(duration_vector_1), median(duration_vector_2)});

	if (CHECK_CORRECTNESS)
	if (run_mkl == 1 && run_tiramisu == 1)
	{
		compare_buffers("sgemm", C, C_mkl);
	}

	if (PRINT_OUTPUT)
	{
	std::cout << "Tiramisu sgemm " << std::endl;
	print_buffer(C);
	std::cout << "MKL sgemm " << std::endl;
	print_buffer(C_mkl);
	}
	}
	return 0;
}
<|endoftext|>


<commit_before>#include <af/seq.h>
#include <af/array.h>
#include <af/data.h>
#include "error.hpp"

namespace af
{

AFAPI int end = -1;
AFAPI seq span(af_span);

void seq::init(double begin, double end, double step)
{
    this->s.begin = begin;
    this->s.end   = end;
    this->s.step  = step;
    if(step != 0) {       // Not Span
        size = fabs((end - begin) / step) + 1;
    } else {
        size = 0;
    }
}

#ifndef signbit
// wtf windows?!
inline int signbit(double x)
{
    if (x < 0) return -1;
    return  0;
}
#endif

seq::~seq()
{
}

seq::seq(double n): m_gfor(false)
{
    if (n < 0) {
        init(n + 1, 0, 1);  // seq(-4) = -3, -2, -1, 0
    } else {
        init(0, n - 1, 1);
    }
}

seq::seq(const af_seq& s_): m_gfor(false)
{
    init(s_.begin, s_.end, s_.step);
}

seq& seq::operator=(const af_seq& s_)
{
    init(s_.begin, s_.end, s_.step);
    return *this;
}

seq::seq(double begin, double end, double step): m_gfor(false)
{
    if(begin == -1 && end <= -1) {
        step = 0;           // end
    }

    if (step == 0) {
        if (begin != end)   // Span
            AF_THROW_MSG("Invalid step size", AF_ERR_INVALID_ARG);
    }
    if (end >= 0 && begin >= 0 && signbit(end-begin) != signbit(step))
        AF_THROW_MSG("Sequence is invalid", AF_ERR_INVALID_ARG);
        //AF_THROW("step must match direction of sequence");
    init(begin, end, step);
}

seq::seq(seq other, bool is_gfor): m_gfor(is_gfor)
{
    this->s = other.s;
    this->size = other.size;
}

seq::operator array() const
{
    dim_type diff = s.end - s.begin;
    dim_type len = (int)((diff + abs(s.step) * (signbit(diff) == 0 ? 1 : -1)) / s.step);
    array tmp = (m_gfor) ? range(1, 1, 1, len) : range(len);
    array res = s.begin + s.step * tmp;
    return res;
}

}
<commit_msg>BUGFIX: Fixed bug in seq to array casting inside gfor<commit_after>#include <af/seq.h>
#include <af/array.h>
#include <af/data.h>
#include "error.hpp"

namespace af
{

AFAPI int end = -1;
AFAPI seq span(af_span);

void seq::init(double begin, double end, double step)
{
    this->s.begin = begin;
    this->s.end   = end;
    this->s.step  = step;
    if(step != 0) {       // Not Span
        size = fabs((end - begin) / step) + 1;
    } else {
        size = 0;
    }
}

#ifndef signbit
// wtf windows?!
inline int signbit(double x)
{
    if (x < 0) return -1;
    return  0;
}
#endif

seq::~seq()
{
}

seq::seq(double n): m_gfor(false)
{
    if (n < 0) {
        init(n + 1, 0, 1);  // seq(-4) = -3, -2, -1, 0
    } else {
        init(0, n - 1, 1);
    }
}

seq::seq(const af_seq& s_): m_gfor(false)
{
    init(s_.begin, s_.end, s_.step);
}

seq& seq::operator=(const af_seq& s_)
{
    init(s_.begin, s_.end, s_.step);
    return *this;
}

seq::seq(double begin, double end, double step): m_gfor(false)
{
    if(begin == -1 && end <= -1) {
        step = 0;           // end
    }

    if (step == 0) {
        if (begin != end)   // Span
            AF_THROW_MSG("Invalid step size", AF_ERR_INVALID_ARG);
    }
    if (end >= 0 && begin >= 0 && signbit(end-begin) != signbit(step))
        AF_THROW_MSG("Sequence is invalid", AF_ERR_INVALID_ARG);
        //AF_THROW("step must match direction of sequence");
    init(begin, end, step);
}

seq::seq(seq other, bool is_gfor): m_gfor(is_gfor)
{
    this->s = other.s;
    this->size = other.size;
}

seq::operator array() const
{
    dim_type diff = s.end - s.begin;
    dim_type len = (int)((diff + abs(s.step) * (signbit(diff) == 0 ? 1 : -1)) / s.step);

    array tmp = (m_gfor) ? range(1, 1, 1, len, 3) : range(len);

    array res = s.begin + s.step * tmp;
    return res;
}

}
<|endoftext|>


<commit_before>#include "factory.h"
#ifdef USE_OPENCV
#include "opencv_video_source.h"
#include "opencv_video_target.h"
#endif // USE_OPENCV
#ifdef USE_FFMPEG
#include "ffmpeg_video_target.h"
#endif
#ifdef USE_I420
#ifdef USE_EPIPHANSDK
#include "epiphansdk_video_source.h"
#endif
#ifdef USE_LIBVLC
#include "vlc_video_source.h"
#endif
#endif

namespace gg {

IVideoSource * Factory::_sources[2] = { NULL, NULL };

IVideoSource * Factory::connect(enum Device type) {
#ifdef USE_I420
    std::string device_id = "";
#ifndef USE_EPIPHANSDK
    throw VideoSourceError("I420 colour space supported only with EpiphanSDK");
#endif
#else
    int device_id = -1; // default value makes no sense
#endif

    switch (type) {
    case DVI2PCIeDuo_DVI:
#ifdef USE_I420
#ifdef USE_EPIPHANSDK
#ifdef EpiphanSDK_DVI
        device_id = EpiphanSDK_DVI;
#else
        throw DeviceNotFound("EpiphanSDK_DVI macro not defined");
#endif
#endif

#ifdef USE_LIBVLC
        device_id = ""; // TODO
#endif
#else
        device_id = 0; // always /dev/video0
#endif
        break;
    case DVI2PCIeDuo_SDI:
#ifdef USE_I420
#ifdef USE_EPIPHANSDK
#ifdef EpiphanSDK_SDI
        device_id = EpiphanSDK_SDI;
#else
        throw DeviceNotFound("EpiphanSDK_SDI macro not defined");
#endif
#endif

#ifdef USE_LIBVLC
        device_id = ""; // TODO
#endif
#else
        device_id = 1; // always /dev/video1
#endif
        break;
    default:
        std::string msg;
        msg.append("Device ")
           .append(std::to_string(type))
           .append(" not recognised");
        throw DeviceNotFound(msg);
    }

    if (_sources[(int) type] == NULL)
    {
        IVideoSource * src = nullptr;
#ifdef USE_I420
#ifdef USE_EPIPHANSDK
        try
        {
            src = new VideoSourceEpiphanSDK(device_id,
                                            V2U_GRABFRAME_FORMAT_I420);
        }
        catch (VideoSourceError & e)
        {
            throw DeviceNotFound(e.what());
        }
#endif

#ifdef USE_LIBVLC
        try
        {
            src = new VideoSourceVLC(device_id);
        }
        catch (VideoSourceError & e)
        {
            throw DeviceNotFound(e.what());
        }
#endif
#else
#ifdef USE_OPENCV
        src = new VideoSourceOpenCV(device_id);
#else
        std::string msg;
        msg.append("Device ")
           .append(std::to_string(type))
           .append(" not supported");
        throw VideoSourceError(msg);
#endif // USE_OPENCV
#endif

        // check querying frame dimensions
        int width = -1, height = -1;
        if (not src->get_frame_dimensions(width, height))
        {
            std::string error;
            error.append("Device ")
#ifdef USE_I420
                 .append(device_id)
#else
                 .append(std::to_string(device_id))
#endif
                 .append(" connected, but ")
                 .append(" does not return frame dimensions.");
            throw DeviceOffline(error);
        }

        // check meaningful frame dimensions
        if (width <= 0 or height <= 0)
        {
            std::string error;
            error.append("Device ")
#ifdef USE_I420
                 .append(device_id)
#else
                 .append(std::to_string(device_id))
#endif
                 .append(" connected, but ")
                 .append(" returns meaningless frame dimensions.");
            throw DeviceOffline(error);
        }

        // check querying frames
#ifdef USE_I420
        VideoFrame_I420 frame;
#else
        VideoFrame_BGRA frame;
#endif
        if (not src->get_frame(frame))
        {
            std::string error;
            error.append("Device ")
#ifdef USE_I420
                 .append(device_id)
#else
                 .append(std::to_string(device_id))
#endif
                 .append(" connected, but ")
                 .append(" does not return frames.");
            throw DeviceOffline(error);
        }

        // if no exception raised up to here, glory be to GiftGrab
        _sources[(int) type] = src;
    }

    return _sources[(int) type];
}

void Factory::disconnect(enum Device type) {
    switch (type) {
    case DVI2PCIeDuo_DVI:
    case DVI2PCIeDuo_SDI:
        break; // everything up to here is recognised
    default:
        std::string msg;
        msg.append("Device ")
           .append(std::to_string(type))
           .append(" not recognised");
        throw DeviceNotFound(msg);
    }

    if (_sources[(int) type])
    {
        delete _sources[(int) type];
        _sources[(int) type] = NULL;
    }
}

IVideoTarget * Factory::writer(Storage type)
{
    switch (type)
    {
    case File_XviD:
#ifdef USE_OPENCV
        return new VideoTargetOpenCV("XVID");
#endif // USE_OPENCV
    case File_HEVC:
#ifdef USE_FFMPEG
        return new VideoTargetFFmpeg("HEVC");
#else
        // nop, see default below
#endif
    case File_VP9:
#ifdef USE_FFMPEG
        return new VideoTargetFFmpeg("VP9");
#else
        // nop, see default below
#endif
    default:
        std::string msg;
        msg.append("Video target type ")
           .append(std::to_string(type))
           .append(" not supported");
        throw VideoTargetError(msg);
    }
}

}
<commit_msg>Issue #83: factory constructing VLC video source with /dev/video* path for Epiphan<commit_after>#include "factory.h"
#ifdef USE_OPENCV
#include "opencv_video_source.h"
#include "opencv_video_target.h"
#endif // USE_OPENCV
#ifdef USE_FFMPEG
#include "ffmpeg_video_target.h"
#endif
#ifdef USE_I420
#ifdef USE_EPIPHANSDK
#include "epiphansdk_video_source.h"
#endif
#ifdef USE_LIBVLC
#include "vlc_video_source.h"
#endif
#endif

namespace gg {

IVideoSource * Factory::_sources[2] = { NULL, NULL };

IVideoSource * Factory::connect(enum Device type) {
#ifdef USE_I420
    std::string device_id = "";
#ifndef USE_EPIPHANSDK
    throw VideoSourceError("I420 colour space supported only with EpiphanSDK");
#endif
#else
    int device_id = -1; // default value makes no sense
#endif

    switch (type) {
    case DVI2PCIeDuo_DVI:
#ifdef USE_I420
#ifdef USE_EPIPHANSDK
#ifdef EpiphanSDK_DVI
        device_id = EpiphanSDK_DVI;
#else
        throw DeviceNotFound("EpiphanSDK_DVI macro not defined");
#endif
#endif

#ifdef USE_LIBVLC
        device_id = "v4l2:///dev/video0"; // always /dev/video0
#endif
#else
        device_id = 0; // always /dev/video0
#endif
        break;
    case DVI2PCIeDuo_SDI:
#ifdef USE_I420
#ifdef USE_EPIPHANSDK
#ifdef EpiphanSDK_SDI
        device_id = EpiphanSDK_SDI;
#else
        throw DeviceNotFound("EpiphanSDK_SDI macro not defined");
#endif
#endif

#ifdef USE_LIBVLC
        device_id = "v4l2:///dev/video1"; // always /dev/video1
#endif
#else
        device_id = 1; // always /dev/video1
#endif
        break;
    default:
        std::string msg;
        msg.append("Device ")
           .append(std::to_string(type))
           .append(" not recognised");
        throw DeviceNotFound(msg);
    }

    if (_sources[(int) type] == NULL)
    {
        IVideoSource * src = nullptr;
#ifdef USE_I420
#ifdef USE_EPIPHANSDK
        try
        {
            src = new VideoSourceEpiphanSDK(device_id,
                                            V2U_GRABFRAME_FORMAT_I420);
        }
        catch (VideoSourceError & e)
        {
            throw DeviceNotFound(e.what());
        }
#endif

#ifdef USE_LIBVLC
        try
        {
            src = new VideoSourceVLC(device_id);
        }
        catch (VideoSourceError & e)
        {
            throw DeviceNotFound(e.what());
        }
#endif
#else
#ifdef USE_OPENCV
        src = new VideoSourceOpenCV(device_id);
#else
        std::string msg;
        msg.append("Device ")
           .append(std::to_string(type))
           .append(" not supported");
        throw VideoSourceError(msg);
#endif // USE_OPENCV
#endif

        // check querying frame dimensions
        int width = -1, height = -1;
        if (not src->get_frame_dimensions(width, height))
        {
            std::string error;
            error.append("Device ")
#ifdef USE_I420
                 .append(device_id)
#else
                 .append(std::to_string(device_id))
#endif
                 .append(" connected, but ")
                 .append(" does not return frame dimensions.");
            throw DeviceOffline(error);
        }

        // check meaningful frame dimensions
        if (width <= 0 or height <= 0)
        {
            std::string error;
            error.append("Device ")
#ifdef USE_I420
                 .append(device_id)
#else
                 .append(std::to_string(device_id))
#endif
                 .append(" connected, but ")
                 .append(" returns meaningless frame dimensions.");
            throw DeviceOffline(error);
        }

        // check querying frames
#ifdef USE_I420
        VideoFrame_I420 frame;
#else
        VideoFrame_BGRA frame;
#endif
        if (not src->get_frame(frame))
        {
            std::string error;
            error.append("Device ")
#ifdef USE_I420
                 .append(device_id)
#else
                 .append(std::to_string(device_id))
#endif
                 .append(" connected, but ")
                 .append(" does not return frames.");
            throw DeviceOffline(error);
        }

        // if no exception raised up to here, glory be to GiftGrab
        _sources[(int) type] = src;
    }

    return _sources[(int) type];
}

void Factory::disconnect(enum Device type) {
    switch (type) {
    case DVI2PCIeDuo_DVI:
    case DVI2PCIeDuo_SDI:
        break; // everything up to here is recognised
    default:
        std::string msg;
        msg.append("Device ")
           .append(std::to_string(type))
           .append(" not recognised");
        throw DeviceNotFound(msg);
    }

    if (_sources[(int) type])
    {
        delete _sources[(int) type];
        _sources[(int) type] = NULL;
    }
}

IVideoTarget * Factory::writer(Storage type)
{
    switch (type)
    {
    case File_XviD:
#ifdef USE_OPENCV
        return new VideoTargetOpenCV("XVID");
#endif // USE_OPENCV
    case File_HEVC:
#ifdef USE_FFMPEG
        return new VideoTargetFFmpeg("HEVC");
#else
        // nop, see default below
#endif
    case File_VP9:
#ifdef USE_FFMPEG
        return new VideoTargetFFmpeg("VP9");
#else
        // nop, see default below
#endif
    default:
        std::string msg;
        msg.append("Video target type ")
           .append(std::to_string(type))
           .append(" not supported");
        throw VideoTargetError(msg);
    }
}

}
<|endoftext|>