<commit_before>// rbOOmit: An implementation of the Certified Reduced Basis method.
// Copyright (C) 2009, 2010 David J. Knezevic

// This file is part of rbOOmit.

// rbOOmit is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.

// rbOOmit is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.

// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

#include "transient_rb_param_subdomain_node.h"
#include "transient_rb_param_subdomain_tree.h"
#include "transient_rb_system.h"
#include "libmesh_logging.h"

namespace libMesh
{

TransientRBParamSubdomainNode::TransientRBParamSubdomainNode(TransientRBParamSubdomainTree& tree_in,
        const std::vector<Real>& anchor_in)
        : Parent(tree_in, anchor_in)
{ }

void TransientRBParamSubdomainNode::add_child(const std::vector<Real>& new_anchor, Child c)
{
  START_LOG("add_child()", "TransientRBParamSubdomainNode");

  // cast the tree reference to a TransientRBParamSubdomainTree
  TransientRBParamSubdomainTree& trans_tree =
    libmesh_cast_ref<TransientRBParamSubdomainTree&>(_tree);

  if(c == LEFT)
  {
    if(left_child != NULL)
    {
      std::cout << "Error: Child already exists!"
                << std::endl;
      libmesh_error();
    }
    else
    {
      // Allocate a new child node
      left_child = new TransientRBParamSubdomainNode(trans_tree, new_anchor);
    }
  }

  if(c == RIGHT)
  {
    if(right_child != NULL)
    {
      std::cout << "Error: Child already exists!"
                << std::endl;
      libmesh_error();
    }
    else
    {
      // Allocate a new child node
      right_child = new TransientRBParamSubdomainNode(trans_tree, new_anchor);
    }
  }

  STOP_LOG("add_child()", "TransientRBParamSubdomainNode");
}

void TransientRBParamSubdomainNode::hp_greedy()
{
    _rb_system.clear_basis_function_dependent_data();

    // Load the (full or subsampled) training set
    if(_tree.n_subsampled_training_points >= n_global_training_parameters())
    {
      _rb_system.load_training_set( training_set );
    }
    else
    {
      std::vector< std::vector<Number> > subsampled_training_set = get_subsampled_training_set();
      _rb_system.load_training_set( subsampled_training_set );
    }

    _rb_system.set_current_parameters( this->anchor );
    _rb_system.set_training_tolerance(_tree.h_tol);

    Real greedy_bound;

    // These casts have to succeed
    TransientRBParamSubdomainTree& trans_tree =
      libmesh_cast_ref<TransientRBParamSubdomainTree&>(_tree);

    TransientRBSystem& trans_rb = libmesh_cast_ref<TransientRBSystem&>(_rb_system);

    // Set the maximum number of truth solves to N_bar in the time-dependent case
    trans_rb.set_max_truth_solves(_tree.N_bar);

    if (!trans_tree.use_delta_N_in_h_stage)
    {
        trans_rb.set_POD_tol(_tree.h_tol/trans_tree.conserv_factor);
    }
    else
    {
        trans_rb.set_POD_tol(-1.);
    }

    // delta_N might be changed in basis training in the transient case
    // (i.e., if we're using POD_tol, or if we hit Nmax)
    // hence we save and reload delta_N
    unsigned int saved_delta_N = trans_rb.get_delta_N();
    greedy_bound = trans_rb.train_reduced_basis();
    // Reload delta_N
    trans_rb.set_delta_N(saved_delta_N);

    trans_rb.set_current_parameters(this->anchor);
    Real RB_error = trans_rb.RB_solve(trans_rb.get_n_basis_functions());
    if (RB_error > _tree.h_tol/trans_tree.conserv_factor)
    {
        std::cout << "Error: The h-tolerance was not satisfied at the "
        << "anchor point hence h-type refinement may not converge."
        << std::endl;
        libmesh_error();
    }

    if ( greedy_bound > _tree.h_tol) // recursive call to hp_greedy
    {
        std::cout << "h tolerance not satisfied, splitting subdomain..." << std::endl;
        split_this_subdomain(true);

        left_child->hp_greedy();
        right_child->hp_greedy();
    }
    else // terminate branch, populate the model with standard p-type,write out subelement data
    {
        std::cout << "h tolerance satisfied, performing p-refinement..." << std::endl;
        greedy_bound = perform_p_stage(greedy_bound);
        if (greedy_bound > _tree.p_tol)
        {
            std::cout << "p tolerance not satisfied, splitting subdomain..." << std::endl;
            split_this_subdomain(false);

            left_child->hp_greedy();
            right_child->hp_greedy();
        }
        else
        {
            std::cout << "p tolerance satisfied, subdomain "
                      << _tree.leaf_node_index << " is a leaf node..."
                      << std::endl;

            // Finally, write out the data for this subdomain
            write_subdomain_data_to_files();
            _tree.leaf_node_index++;
        }
    }
}

Real TransientRBParamSubdomainNode::perform_p_stage(Real greedy_bound)
{
    START_LOG("perform_p_stage()", "TransientRBParamSubdomainNode");

    // Continue the greedy process on this subdomain, i.e.
    // we do not discard the basis functions generated for
    // this subdomain in the h-refinement phase
    _rb_system.set_training_tolerance(_tree.p_tol);

    TransientRBSystem& trans_rb = libmesh_cast_ref<TransientRBSystem&>(_rb_system);

    // Ignore max_truth_solves and POD-tol in the p-stage
    trans_rb.set_POD_tol(-1.);
    trans_rb.set_max_truth_solves(-1);

    // Clear the reduced basis and reinitialize the greedy to the anchor point
    trans_rb.clear_basis_function_dependent_data();
    trans_rb.set_current_parameters( this->anchor );

    // Checking if p-tol is already satisfied or Nmax has been reached
    // if not do another (standard) greedy
    if ( (greedy_bound > _tree.p_tol) || (_rb_system.get_n_basis_functions() < _rb_system.get_Nmax()) )
    {
        greedy_bound = _rb_system.train_reduced_basis();
    }

    STOP_LOG("perform_p_stage()", "TransientRBParamSubdomainNode");

    return greedy_bound;
}

void TransientRBParamSubdomainNode::split_this_subdomain(bool h_stage_split)
{
    START_LOG("split_this_subdomain()", "TransientRBParamSubdomainNode");

    // These first few lines are the same as RBParamSubdomainNode::split_this_subdomain
    this->add_child( _rb_system.get_greedy_parameter(0), RBParamSubdomainNode::LEFT);
    this->add_child( _rb_system.get_greedy_parameter(1), RBParamSubdomainNode::RIGHT);

    // Compute distance between the children anchor points, and pass to children (JLE 2010-09-16)
    Real distance_between_children_anchors = 0.;
    for (unsigned int i = 0; i < left_child->anchor.size(); i++)
    {
        distance_between_children_anchors += std::pow((left_child->anchor[i] - right_child->anchor[i]),2.);
    }
    distance_between_children_anchors = std::sqrt(distance_between_children_anchors);
    left_child->distance_between_anchors = distance_between_children_anchors;
    right_child->distance_between_anchors = distance_between_children_anchors;

    // We now need some code specific to the transient case because it
    // is possible that we have repeated selection of training points
    // in the transient case (due to the POD-Greedy) and hence we
    // may have distance_between_children_anchors == 0.
    bool anchors_are_equal = (distance_between_children_anchors == 0.);

    if (h_stage_split)
    {
        if (anchors_are_equal)
        {
            std::cout << "Error: Anchor points for children are equal!"
                      << std::endl;
            libmesh_error();
        }
    }
    else
    {
        if (anchors_are_equal)
        {
            for (unsigned int i=2; i< _rb_system.greedy_param_list.size() ; i++)
            {
                bool parameters_are_equal = true;
                for (unsigned int  j = 0; j < left_child->anchor.size(); j++)
                {
                    parameters_are_equal = ( parameters_are_equal && (left_child->anchor[j] == _rb_system.get_greedy_parameter(i)[j]));
                }
                if (!parameters_are_equal)
                {
                    right_child->anchor = _rb_system.get_greedy_parameter(i);
                    anchors_are_equal = false;
                    break;
                }
            }

            // anchors_are_equal has been updated, check if we have found different point.
            if(anchors_are_equal)
            {
                std::cout << "Error: Unable to find distinct anchors in additional splitting step." << std::endl;
                libmesh_error();
            }
        }
    }

    this->initialize_child_training_sets();

    STOP_LOG("split_this_subdomain()", "TransientRBParamSubdomainNode");
}

} // namespace libMesh
<commit_msg>Fixing single precision regression<commit_after>// rbOOmit: An implementation of the Certified Reduced Basis method.
// Copyright (C) 2009, 2010 David J. Knezevic

// This file is part of rbOOmit.

// rbOOmit is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.

// rbOOmit is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.

// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

#include "transient_rb_param_subdomain_node.h"
#include "transient_rb_param_subdomain_tree.h"
#include "transient_rb_system.h"
#include "libmesh_logging.h"

namespace libMesh
{

TransientRBParamSubdomainNode::TransientRBParamSubdomainNode(TransientRBParamSubdomainTree& tree_in,
        const std::vector<Real>& anchor_in)
        : Parent(tree_in, anchor_in)
{ }

void TransientRBParamSubdomainNode::add_child(const std::vector<Real>& new_anchor, Child c)
{
  START_LOG("add_child()", "TransientRBParamSubdomainNode");

  // cast the tree reference to a TransientRBParamSubdomainTree
  TransientRBParamSubdomainTree& trans_tree =
    libmesh_cast_ref<TransientRBParamSubdomainTree&>(_tree);

  if(c == LEFT)
  {
    if(left_child != NULL)
    {
      std::cout << "Error: Child already exists!"
                << std::endl;
      libmesh_error();
    }
    else
    {
      // Allocate a new child node
      left_child = new TransientRBParamSubdomainNode(trans_tree, new_anchor);
    }
  }

  if(c == RIGHT)
  {
    if(right_child != NULL)
    {
      std::cout << "Error: Child already exists!"
                << std::endl;
      libmesh_error();
    }
    else
    {
      // Allocate a new child node
      right_child = new TransientRBParamSubdomainNode(trans_tree, new_anchor);
    }
  }

  STOP_LOG("add_child()", "TransientRBParamSubdomainNode");
}

void TransientRBParamSubdomainNode::hp_greedy()
{
    _rb_system.clear_basis_function_dependent_data();

    // Load the (full or subsampled) training set
    if(_tree.n_subsampled_training_points >= n_global_training_parameters())
    {
      _rb_system.load_training_set( training_set );
    }
    else
    {
      std::vector< std::vector<Number> > subsampled_training_set = get_subsampled_training_set();
      _rb_system.load_training_set( subsampled_training_set );
    }

    _rb_system.set_current_parameters( this->anchor );
    _rb_system.set_training_tolerance(_tree.h_tol);

    Real greedy_bound;

    // These casts have to succeed
    TransientRBParamSubdomainTree& trans_tree =
      libmesh_cast_ref<TransientRBParamSubdomainTree&>(_tree);

    TransientRBSystem& trans_rb = libmesh_cast_ref<TransientRBSystem&>(_rb_system);

    // Set the maximum number of truth solves to N_bar in the time-dependent case
    trans_rb.set_max_truth_solves(_tree.N_bar);

    if (!trans_tree.use_delta_N_in_h_stage)
    {
        trans_rb.set_POD_tol(_tree.h_tol/trans_tree.conserv_factor);
    }
    else
    {
        trans_rb.set_POD_tol(-1.);
    }

    // delta_N might be changed in basis training in the transient case
    // (i.e., if we're using POD_tol, or if we hit Nmax)
    // hence we save and reload delta_N
    unsigned int saved_delta_N = trans_rb.get_delta_N();
    greedy_bound = trans_rb.train_reduced_basis();
    // Reload delta_N
    trans_rb.set_delta_N(saved_delta_N);

    trans_rb.set_current_parameters(this->anchor);
    Real RB_error = trans_rb.RB_solve(trans_rb.get_n_basis_functions());
    if (RB_error > _tree.h_tol/trans_tree.conserv_factor)
    {
        std::cout << "Error: The h-tolerance was not satisfied at the "
        << "anchor point hence h-type refinement may not converge."
        << std::endl;
        libmesh_error();
    }

    if ( greedy_bound > _tree.h_tol) // recursive call to hp_greedy
    {
        std::cout << "h tolerance not satisfied, splitting subdomain..." << std::endl;
        split_this_subdomain(true);

        left_child->hp_greedy();
        right_child->hp_greedy();
    }
    else // terminate branch, populate the model with standard p-type,write out subelement data
    {
        std::cout << "h tolerance satisfied, performing p-refinement..." << std::endl;
        greedy_bound = perform_p_stage(greedy_bound);
        if (greedy_bound > _tree.p_tol)
        {
            std::cout << "p tolerance not satisfied, splitting subdomain..." << std::endl;
            split_this_subdomain(false);

            left_child->hp_greedy();
            right_child->hp_greedy();
        }
        else
        {
            std::cout << "p tolerance satisfied, subdomain "
                      << _tree.leaf_node_index << " is a leaf node..."
                      << std::endl;

            // Finally, write out the data for this subdomain
            write_subdomain_data_to_files();
            _tree.leaf_node_index++;
        }
    }
}

Real TransientRBParamSubdomainNode::perform_p_stage(Real greedy_bound)
{
    START_LOG("perform_p_stage()", "TransientRBParamSubdomainNode");

    // Continue the greedy process on this subdomain, i.e.
    // we do not discard the basis functions generated for
    // this subdomain in the h-refinement phase
    _rb_system.set_training_tolerance(_tree.p_tol);

    TransientRBSystem& trans_rb = libmesh_cast_ref<TransientRBSystem&>(_rb_system);

    // Ignore max_truth_solves and POD-tol in the p-stage
    trans_rb.set_POD_tol(-1.);
    trans_rb.set_max_truth_solves(-1);

    // Clear the reduced basis and reinitialize the greedy to the anchor point
    trans_rb.clear_basis_function_dependent_data();
    trans_rb.set_current_parameters( this->anchor );

    // Checking if p-tol is already satisfied or Nmax has been reached
    // if not do another (standard) greedy
    if ( (greedy_bound > _tree.p_tol) || (_rb_system.get_n_basis_functions() < _rb_system.get_Nmax()) )
    {
        greedy_bound = _rb_system.train_reduced_basis();
    }

    STOP_LOG("perform_p_stage()", "TransientRBParamSubdomainNode");

    return greedy_bound;
}

void TransientRBParamSubdomainNode::split_this_subdomain(bool h_stage_split)
{
    START_LOG("split_this_subdomain()", "TransientRBParamSubdomainNode");

    // These first few lines are the same as RBParamSubdomainNode::split_this_subdomain
    this->add_child( _rb_system.get_greedy_parameter(0), RBParamSubdomainNode::LEFT);
    this->add_child( _rb_system.get_greedy_parameter(1), RBParamSubdomainNode::RIGHT);

    // Compute distance between the children anchor points, and pass to children (JLE 2010-09-16)
    Real distance_between_children_anchors = 0.;
    for (unsigned int i = 0; i < left_child->anchor.size(); i++)
    {
        distance_between_children_anchors += std::pow((left_child->anchor[i] - right_child->anchor[i]),Real(2.));
    }
    distance_between_children_anchors = std::sqrt(distance_between_children_anchors);
    left_child->distance_between_anchors = distance_between_children_anchors;
    right_child->distance_between_anchors = distance_between_children_anchors;

    // We now need some code specific to the transient case because it
    // is possible that we have repeated selection of training points
    // in the transient case (due to the POD-Greedy) and hence we
    // may have distance_between_children_anchors == 0.
    bool anchors_are_equal = (distance_between_children_anchors == 0.);

    if (h_stage_split)
    {
        if (anchors_are_equal)
        {
            std::cout << "Error: Anchor points for children are equal!"
                      << std::endl;
            libmesh_error();
        }
    }
    else
    {
        if (anchors_are_equal)
        {
            for (unsigned int i=2; i< _rb_system.greedy_param_list.size() ; i++)
            {
                bool parameters_are_equal = true;
                for (unsigned int  j = 0; j < left_child->anchor.size(); j++)
                {
                    parameters_are_equal = ( parameters_are_equal && (left_child->anchor[j] == _rb_system.get_greedy_parameter(i)[j]));
                }
                if (!parameters_are_equal)
                {
                    right_child->anchor = _rb_system.get_greedy_parameter(i);
                    anchors_are_equal = false;
                    break;
                }
            }

            // anchors_are_equal has been updated, check if we have found different point.
            if(anchors_are_equal)
            {
                std::cout << "Error: Unable to find distinct anchors in additional splitting step." << std::endl;
                libmesh_error();
            }
        }
    }

    this->initialize_child_training_sets();

    STOP_LOG("split_this_subdomain()", "TransientRBParamSubdomainNode");
}

} // namespace libMesh
<|endoftext|>


<commit_before>/**
 * Open[Flex] Board View
 *
 * Copyright chloridite 2016
 * Copyright inflex 2016 (Paul Daniels)
 *
 * Git Fork: https://github.com/inflex/OpenBoardView
 *
 */
#include "BoardView.h"

#include "imgui_impl_dx9.h"
#include <d3d9.h>
#define DIRECTINPUT_VERSION 0x0800
#include "platform.h"
#include "confparse.h"
#include "crtdbg.h"
#include "resource.h"
#include <dinput.h>
#include <direct.h>
#include <shlwapi.h>
#include <tchar.h>

// Data
static LPDIRECT3DDEVICE9 g_pd3dDevice = NULL;
static D3DPRESENT_PARAMETERS g_d3dpp;

// local functions
#ifndef S_ISDIR
#define S_ISDIR(mode) (((mode)&S_IFMT) == S_IFDIR)
#endif
uint32_t byte4swap(uint32_t x) {
	/*
	* used to convert RGBA -> ABGR etc
	*/
	return (((x & 0x000000ff) << 24) | ((x & 0x0000ff00) << 8) | ((x & 0x00ff0000) >> 8) | ((x & 0xff000000) >> 24));
}

extern LRESULT ImGui_ImplDX9_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
	if (ImGui_ImplDX9_WndProcHandler(hWnd, msg, wParam, lParam)) return true;

	switch (msg) {
		case WM_SIZE:
			if (g_pd3dDevice != NULL && wParam != SIZE_MINIMIZED) {
				ImGui_ImplDX9_InvalidateDeviceObjects();
				g_d3dpp.BackBufferWidth  = LOWORD(lParam);
				g_d3dpp.BackBufferHeight = HIWORD(lParam);
				HRESULT hr               = g_pd3dDevice->Reset(&g_d3dpp);
				if (hr == D3DERR_INVALIDCALL) IM_ASSERT(0);
				ImGui_ImplDX9_CreateDeviceObjects();
			}
			return 0;
		case WM_SYSCOMMAND:
			if ((wParam & 0xfff0) == SC_KEYMENU) // Disable ALT application menu
				return 0;
			break;
		case WM_DESTROY: PostQuitMessage(0); return 0;
	}
	return DefWindowProc(hWnd, msg, wParam, lParam);
}

int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {

	// Initialize comctl
	CoInitializeEx(NULL, COINIT_MULTITHREADED);

	char ss[1025];
	char *homepath;
	int err;
	size_t hpsz;
	// Confparse obvconfig;
	int sizex, sizey;
	bool use_exepath  = false;
	bool use_homepath = true;
	BoardView app{};
	CHAR history_file[MAX_PATH];
	CHAR conf_file[MAX_PATH];

	static const wchar_t *class_name = L"Openflex Board View";

	/*
	 * To make OBV very easy to use and transportable among windows
	 * users, one method is to just make it do all its business in the
	 * folder that the EXE is launched from.  It's not "proper" but
	 * it is very simple and it works.
	 */
	HMODULE hModule = GetModuleHandleA(NULL);
	CHAR exepath[MAX_PATH];
	GetModuleFileNameA(hModule, exepath, MAX_PATH);

	/*
	 * Trim off the filename at the end of the path
	 */
	int l = strlen(exepath);
	while (--l) {
		if (exepath[l] == '\\') {
			exepath[l] = '\0';
			break;
		}
	}
	snprintf(history_file, sizeof(history_file), "%s\\obv.history", exepath);
	snprintf(conf_file, sizeof(conf_file), "%s\\obv.conf", exepath);

	/*
	 * Next, we check to see if there's an APPDATA folder that's
	 * already setup with our name on it.  This will be the case
	 * if OBV has been 'installed', even via the simple install.bat
	 * script.
	 */
	err = _dupenv_s(&homepath, &hpsz, "APPDATA");
	if (homepath) {
		struct stat st;
		int sr;
		snprintf(ss, sizeof(ss), "%s/openboardview", homepath);
		sr = stat(ss, &st);
		if (sr == -1) {
			//_mkdir(ss);
			// sr = stat(ss, &st);
		} else {
			snprintf(history_file, sizeof(history_file), "%s\\obv.history", homepath);
			snprintf(conf_file, sizeof(conf_file), "%s\\obv.conf", homepath);
		}
	}

	// Create application window
	HINSTANCE instance = GetModuleHandle(NULL);
	HICON icon         = LoadIcon(instance, MAKEINTRESOURCE(IDI_ICON1));
	WNDCLASSEX wc      = {sizeof(WNDCLASSEX), CS_CLASSDC, WndProc, 0L, 0L, instance, icon, NULL, NULL, NULL, class_name, NULL};
	RegisterClassEx(&wc);

	app.obvconfig.Load(conf_file);
	sizex = app.obvconfig.ParseInt("windowX", 900);
	sizey = app.obvconfig.ParseInt("windowY", 600);

	HWND hwnd = CreateWindow(class_name,
	                         _T("Openflex Board Viewer"),
	                         WS_OVERLAPPEDWINDOW,
	                         CW_USEDEFAULT,
	                         CW_USEDEFAULT,
	                         sizex,
	                         sizey,
	                         NULL,
	                         NULL,
	                         wc.hInstance,
	                         NULL);

	// Initialize Direct3D
	LPDIRECT3D9 pD3D;
	if ((pD3D = Direct3DCreate9(D3D_SDK_VERSION)) == NULL) {
		UnregisterClass(class_name, wc.hInstance);
		return 0;
	}
	ZeroMemory(&g_d3dpp, sizeof(g_d3dpp));
	g_d3dpp.Windowed               = TRUE;
	g_d3dpp.SwapEffect             = D3DSWAPEFFECT_DISCARD;
	g_d3dpp.BackBufferFormat       = D3DFMT_UNKNOWN;
	g_d3dpp.EnableAutoDepthStencil = TRUE;
	g_d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
	g_d3dpp.PresentationInterval   = D3DPRESENT_INTERVAL_ONE;

	// Create the D3DDevice
	if (pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd, D3DCREATE_HARDWARE_VERTEXPROCESSING, &g_d3dpp, &g_pd3dDevice) <
	    0) {
		pD3D->Release();
		UnregisterClass(class_name, wc.hInstance);
		return 0;
	}

	// Setup ImGui binding
	ImGui_ImplDX9_Init(hwnd, g_pd3dDevice);

	// Load Fonts
	// (there is a default font, this is only if you want to change it. see
	// extra_fonts/README.txt
	// for more details)
	ImGuiIO &io    = ImGui::GetIO();
	io.IniFilename = NULL;
	int ttf_size;
	unsigned char *ttf_data = LoadAsset(&ttf_size, ASSET_FIRA_SANS);
	ImFontConfig font_cfg{};
	font_cfg.FontDataOwnedByAtlas = false;
	io.Fonts->AddFontFromMemoryTTF(ttf_data, ttf_size, app.obvconfig.ParseDouble("fontSize", 20.0f), &font_cfg);

	/*
	 * Load the existing file loaded history
	 */
	if (history_file[0] != '\0') {
		app.fhistory.Set_filename(history_file);
		app.fhistory.Load();
	}

	/*
	 * Parse the settings in the configuration file
	 *
	 * There are some settings which have been parsed
	 * earlier but they apply to the startup of the
	 * main, as opposed to OBV itself.  This call
	 * parses all the things that'll influence OBV
	 */
	app.ConfigParse();

	bool show_test_window    = true;
	bool show_another_window = false;
	ImVec4 clear_col         = ImColor(app.m_colors.backgroundColor);

	// Main loop
	MSG msg;
	ZeroMemory(&msg, sizeof(msg));
	ShowWindow(hwnd, SW_SHOWDEFAULT);
	UpdateWindow(hwnd);
	while (msg.message != WM_QUIT) {
		if (PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE)) {
			TranslateMessage(&msg);
			DispatchMessage(&msg);
			continue;
		}
		ImGui_ImplDX9_NewFrame();
		app.Update();
		if (app.m_wantsQuit) {
			PostMessage(hwnd, WM_QUIT, 0, 0);
		}

		// Rendering
		g_pd3dDevice->SetRenderState(D3DRS_ZENABLE, false);
		g_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, false);
		g_pd3dDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, false);
		D3DCOLOR clear_col_dx = D3DCOLOR_RGBA(
		    (int)(clear_col.x * 255.0f), (int)(clear_col.y * 255.0f), (int)(clear_col.z * 255.0f), (int)(clear_col.w * 255.0f));
		g_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, clear_col_dx, 1.0f, 0);
		if (g_pd3dDevice->BeginScene() >= 0) {
			ImGui::Render();
			g_pd3dDevice->EndScene();
		}
		g_pd3dDevice->Present(NULL, NULL, NULL, NULL);
	}

	ImGui_ImplDX9_Shutdown();
	if (g_pd3dDevice) g_pd3dDevice->Release();
	if (pD3D) pD3D->Release();
	UnregisterClass(class_name, wc.hInstance);

	return 0;
}
<commit_msg>Windows dpi font setup<commit_after>/**
 * Open[Flex] Board View
 *
 * Copyright chloridite 2016
 * Copyright inflex 2016 (Paul Daniels)
 *
 * Git Fork: https://github.com/inflex/OpenBoardView
 *
 */
#include "BoardView.h"

#include "imgui_impl_dx9.h"
#include <d3d9.h>
#define DIRECTINPUT_VERSION 0x0800
#include "platform.h"
#include "confparse.h"
#include "crtdbg.h"
#include "resource.h"
#include <dinput.h>
#include <direct.h>
#include <shlwapi.h>
#include <tchar.h>

// Data
static LPDIRECT3DDEVICE9 g_pd3dDevice = NULL;
static D3DPRESENT_PARAMETERS g_d3dpp;

// local functions
#ifndef S_ISDIR
#define S_ISDIR(mode) (((mode)&S_IFMT) == S_IFDIR)
#endif
uint32_t byte4swap(uint32_t x) {
	/*
	* used to convert RGBA -> ABGR etc
	*/
	return (((x & 0x000000ff) << 24) | ((x & 0x0000ff00) << 8) | ((x & 0x00ff0000) >> 8) | ((x & 0xff000000) >> 24));
}

extern LRESULT ImGui_ImplDX9_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
	if (ImGui_ImplDX9_WndProcHandler(hWnd, msg, wParam, lParam)) return true;

	switch (msg) {
		case WM_SIZE:
			if (g_pd3dDevice != NULL && wParam != SIZE_MINIMIZED) {
				ImGui_ImplDX9_InvalidateDeviceObjects();
				g_d3dpp.BackBufferWidth  = LOWORD(lParam);
				g_d3dpp.BackBufferHeight = HIWORD(lParam);
				HRESULT hr               = g_pd3dDevice->Reset(&g_d3dpp);
				if (hr == D3DERR_INVALIDCALL) IM_ASSERT(0);
				ImGui_ImplDX9_CreateDeviceObjects();
			}
			return 0;
		case WM_SYSCOMMAND:
			if ((wParam & 0xfff0) == SC_KEYMENU) // Disable ALT application menu
				return 0;
			break;
		case WM_DESTROY: PostQuitMessage(0); return 0;
	}
	return DefWindowProc(hWnd, msg, wParam, lParam);
}

int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {

	// Initialize comctl
	CoInitializeEx(NULL, COINIT_MULTITHREADED);

	char ss[1025];
	char *homepath;
	int err;
	size_t hpsz;
	// Confparse obvconfig;
	int sizex, sizey;
	bool use_exepath  = false;
	bool use_homepath = true;
	BoardView app{};
	CHAR history_file[MAX_PATH];
	CHAR conf_file[MAX_PATH];

	static const wchar_t *class_name = L"Openflex Board View";

	/*
	 * To make OBV very easy to use and transportable among windows
	 * users, one method is to just make it do all its business in the
	 * folder that the EXE is launched from.  It's not "proper" but
	 * it is very simple and it works.
	 */
	HMODULE hModule = GetModuleHandleA(NULL);
	CHAR exepath[MAX_PATH];
	GetModuleFileNameA(hModule, exepath, MAX_PATH);

	/*
	 * Trim off the filename at the end of the path
	 */
	int l = strlen(exepath);
	while (--l) {
		if (exepath[l] == '\\') {
			exepath[l] = '\0';
			break;
		}
	}
	snprintf(history_file, sizeof(history_file), "%s\\obv.history", exepath);
	snprintf(conf_file, sizeof(conf_file), "%s\\obv.conf", exepath);

	/*
	 * Next, we check to see if there's an APPDATA folder that's
	 * already setup with our name on it.  This will be the case
	 * if OBV has been 'installed', even via the simple install.bat
	 * script.
	 */
	err = _dupenv_s(&homepath, &hpsz, "APPDATA");
	if (homepath) {
		struct stat st;
		int sr;
		snprintf(ss, sizeof(ss), "%s/openboardview", homepath);
		sr = stat(ss, &st);
		if (sr == -1) {
			//_mkdir(ss);
			// sr = stat(ss, &st);
		} else {
			snprintf(history_file, sizeof(history_file), "%s\\obv.history", homepath);
			snprintf(conf_file, sizeof(conf_file), "%s\\obv.conf", homepath);
		}
	}

	// Create application window
	HINSTANCE instance = GetModuleHandle(NULL);
	HICON icon         = LoadIcon(instance, MAKEINTRESOURCE(IDI_ICON1));
	WNDCLASSEX wc      = {sizeof(WNDCLASSEX), CS_CLASSDC, WndProc, 0L, 0L, instance, icon, NULL, NULL, NULL, class_name, NULL};
	RegisterClassEx(&wc);

	app.obvconfig.Load(conf_file);
	sizex = app.obvconfig.ParseInt("windowX", 900);
	sizey = app.obvconfig.ParseInt("windowY", 600);

	HWND hwnd = CreateWindow(class_name,
	                         _T("Openflex Board Viewer"),
	                         WS_OVERLAPPEDWINDOW,
	                         CW_USEDEFAULT,
	                         CW_USEDEFAULT,
	                         sizex,
	                         sizey,
	                         NULL,
	                         NULL,
	                         wc.hInstance,
	                         NULL);

	// Initialize Direct3D
	LPDIRECT3D9 pD3D;
	if ((pD3D = Direct3DCreate9(D3D_SDK_VERSION)) == NULL) {
		UnregisterClass(class_name, wc.hInstance);
		return 0;
	}
	ZeroMemory(&g_d3dpp, sizeof(g_d3dpp));
	g_d3dpp.Windowed               = TRUE;
	g_d3dpp.SwapEffect             = D3DSWAPEFFECT_DISCARD;
	g_d3dpp.BackBufferFormat       = D3DFMT_UNKNOWN;
	g_d3dpp.EnableAutoDepthStencil = TRUE;
	g_d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
	g_d3dpp.PresentationInterval   = D3DPRESENT_INTERVAL_ONE;

	// Create the D3DDevice
	if (pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd, D3DCREATE_HARDWARE_VERTEXPROCESSING, &g_d3dpp, &g_pd3dDevice) <
	    0) {
		pD3D->Release();
		UnregisterClass(class_name, wc.hInstance);
		return 0;
	}

	// Setup ImGui binding
	ImGui_ImplDX9_Init(hwnd, g_pd3dDevice);

	// Load Fonts
	// (there is a default font, this is only if you want to change it. see
	// extra_fonts/README.txt
	// for more details)
	ImGuiIO &io    = ImGui::GetIO();
	io.IniFilename = NULL;

	/*
	 * Load the existing file loaded history
	 */
	if (history_file[0] != '\0') {
		app.fhistory.Set_filename(history_file);
		app.fhistory.Load();
	}

	/*
	 * Parse the settings in the configuration file
	 *
	 * There are some settings which have been parsed
	 * earlier but they apply to the startup of the
	 * main, as opposed to OBV itself.  This call
	 * parses all the things that'll influence OBV
	 */
	app.ConfigParse();

	/*
	 * Set the font based on the dpi
	 */
	int ttf_size;
	unsigned char *ttf_data = LoadAsset(&ttf_size, ASSET_FIRA_SANS);
	ImFontConfig font_cfg{};
	font_cfg.FontDataOwnedByAtlas = false;
	io.Fonts->AddFontFromMemoryTTF(ttf_data, ttf_size, app.obvconfig.ParseDouble("fontSize", 20.0f * (app.dpi / 100.0)), &font_cfg);

	bool show_test_window    = true;
	bool show_another_window = false;
	ImVec4 clear_col         = ImColor(app.m_colors.backgroundColor);

	// Main loop
	MSG msg;
	ZeroMemory(&msg, sizeof(msg));
	ShowWindow(hwnd, SW_SHOWDEFAULT);
	UpdateWindow(hwnd);
	while (msg.message != WM_QUIT) {
		if (PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE)) {
			TranslateMessage(&msg);
			DispatchMessage(&msg);
			continue;
		}
		ImGui_ImplDX9_NewFrame();
		app.Update();
		if (app.m_wantsQuit) {
			PostMessage(hwnd, WM_QUIT, 0, 0);
		}

		// Rendering
		g_pd3dDevice->SetRenderState(D3DRS_ZENABLE, false);
		g_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, false);
		g_pd3dDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, false);
		D3DCOLOR clear_col_dx = D3DCOLOR_RGBA(
		    (int)(clear_col.x * 255.0f), (int)(clear_col.y * 255.0f), (int)(clear_col.z * 255.0f), (int)(clear_col.w * 255.0f));
		g_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, clear_col_dx, 1.0f, 0);
		if (g_pd3dDevice->BeginScene() >= 0) {
			ImGui::Render();
			g_pd3dDevice->EndScene();
		}
		g_pd3dDevice->Present(NULL, NULL, NULL, NULL);
	}

	ImGui_ImplDX9_Shutdown();
	if (g_pd3dDevice) g_pd3dDevice->Release();
	if (pD3D) pD3D->Release();
	UnregisterClass(class_name, wc.hInstance);

	return 0;
}
<|endoftext|>


<commit_before>#include <math.h>
#include "angort.h"

#define FN(f) a->pushFloat(f(a->popFloat()))
%name stdmath

%word cos (x -- cos x)
{
    FN(cosf);
}
%word sin (x -- sin x)
{
    FN(sinf);
}
%word tan (x -- tan x)
{
    FN(tanf);
}
%word ln (x -- ln x)
{
    FN(logf);
}
%word log (x -- ln x)
{
    FN(log10f);
}
%word log2 (x -- log2 x)
{
    FN(log2f);
}
%word sqrt (x -- sqrt x)
{
    FN(sqrtf);
}
<commit_msg>added exp to math<commit_after>#include <math.h>
#include "angort.h"

/*
 * Mappings for (some) standard maths library functions
 */

// macro for helping generate unary float functions
#define FN(f) a->pushFloat(f(a->popFloat()))

%name stdmath

%word cos (x -- cos x)
{
    FN(cosf);
}
%word sin (x -- sin x)
{
    FN(sinf);
}
%word tan (x -- tan x)
{
    FN(tanf);
}
%word ln (x -- ln x)
{
    FN(logf);
}
%word log (x -- ln x)
{
    FN(log10f);
}
%word log2 (x -- log2 x)
{
    FN(log2f);
}
%word sqrt (x -- sqrt x)
{
    FN(sqrtf);
}

%word exp (x -- exp x)
{
    FN(exp);
}
<|endoftext|>


<commit_before>// Copyright (c) 2012 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <string>
#include <time.h>
#include "version.h"

// Name of client reported in the 'version' message. Report the same name
// for both bitcoind and bitcoin-qt, to make it harder for attackers to
// target servers or GUI users specifically.
const std::string CLIENT_NAME("BitBar");

// Client version number
#define CLIENT_VERSION_SUFFIX   "-beta"

// The following part of the code determines the CLIENT_BUILD variable.
// Several mechanisms are used for this:
// * first, if HAVE_BUILD_INFO is defined, include build.h, a file that is
//   generated by the build environment, possibly containing the output
//   of git-describe in a macro called BUILD_DESC
// * secondly, if this is an exported version of the code, GIT_ARCHIVE will
//   be defined (automatically using the export-subst git attribute), and
//   GIT_COMMIT will contain the commit id.
// * then, three options exist for determining CLIENT_BUILD:
//   * if BUILD_DESC is defined, use that literally (output of git-describe)
//   * if not, but GIT_COMMIT is defined, use v[maj].[min].[rev].[build]-g[commit]
//   * otherwise, use v[maj].[min].[rev].[build]-unk
// finally CLIENT_VERSION_SUFFIX is added

// First, include build.h if requested
#ifdef HAVE_BUILD_INFO
#    include "build.h"
#endif

// git will put "#define GIT_ARCHIVE 1" on the next line inside archives.
#define GIT_ARCHIVE 1
#ifdef GIT_ARCHIVE
#    define GIT_COMMIT_ID "32a928e"
#    define GIT_COMMIT_DATE __DATE__
//#    define GIT_COMMIT_DATE "Apr 15 2016"

//   when cross compiling for windows, the commit date shows
//   in the rpcconsole build date as "$Format:%cD"
  time_t t=time(NULL);
  struct tm *tm=localtime(&t);
//  #define GIT_COMMIT_DATE asctime(tm)
#endif

#define BUILD_DESC_FROM_COMMIT(maj,min,rev,build,commit) \
    "v" DO_STRINGIZE(maj) "." DO_STRINGIZE(min) "." DO_STRINGIZE(rev) "." DO_STRINGIZE(build) "-g" commit

#define BUILD_DESC_FROM_UNKNOWN(maj,min,rev,build) \
    "v" DO_STRINGIZE(maj) "." DO_STRINGIZE(min) "." DO_STRINGIZE(rev) "." DO_STRINGIZE(build) "-unk"

#ifndef BUILD_DESC
#    ifdef GIT_COMMIT_ID
#        define BUILD_DESC BUILD_DESC_FROM_COMMIT(DISPLAY_VERSION_MAJOR, DISPLAY_VERSION_MINOR, DISPLAY_VERSION_REVISION, DISPLAY_VERSION_BUILD, GIT_COMMIT_ID)
#    else
#        define BUILD_DESC BUILD_DESC_FROM_UNKNOWN(DISPLAY_VERSION_MAJOR, DISPLAY_VERSION_MINOR, DISPLAY_VERSION_REVISION, DISPLAY_VERSION_BUILD)
#    endif
#endif

#ifndef BUILD_DATE
#    ifdef GIT_COMMIT_DATE
#        define BUILD_DATE GIT_COMMIT_DATE
#    else
#        define BUILD_DATE __DATE__ ", " __TIME__
#    endif
#endif

const std::string CLIENT_BUILD(BUILD_DESC CLIENT_VERSION_SUFFIX);
const std::string CLIENT_DATE(BUILD_DATE);
<commit_msg>Marked for release<commit_after>// Copyright (c) 2012 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <string>
#include <time.h>
#include "version.h"

// Name of client reported in the 'version' message. Report the same name
// for both bitcoind and bitcoin-qt, to make it harder for attackers to
// target servers or GUI users specifically.
const std::string CLIENT_NAME("BitBar");

// Client version number
//#define CLIENT_VERSION_SUFFIX   "-beta"
#define CLIENT_VERSION_SUFFIX   "-release"

// The following part of the code determines the CLIENT_BUILD variable.
// Several mechanisms are used for this:
// * first, if HAVE_BUILD_INFO is defined, include build.h, a file that is
//   generated by the build environment, possibly containing the output
//   of git-describe in a macro called BUILD_DESC
// * secondly, if this is an exported version of the code, GIT_ARCHIVE will
//   be defined (automatically using the export-subst git attribute), and
//   GIT_COMMIT will contain the commit id.
// * then, three options exist for determining CLIENT_BUILD:
//   * if BUILD_DESC is defined, use that literally (output of git-describe)
//   * if not, but GIT_COMMIT is defined, use v[maj].[min].[rev].[build]-g[commit]
//   * otherwise, use v[maj].[min].[rev].[build]-unk
// finally CLIENT_VERSION_SUFFIX is added

// First, include build.h if requested
#ifdef HAVE_BUILD_INFO
#    include "build.h"
#endif

// git will put "#define GIT_ARCHIVE 1" on the next line inside archives.
#define GIT_ARCHIVE 1
#ifdef GIT_ARCHIVE
#    define GIT_COMMIT_ID "32a928e"
#    define GIT_COMMIT_DATE __DATE__
//#    define GIT_COMMIT_DATE "Apr 15 2016"

//   when cross compiling for windows, the commit date shows
//   in the rpcconsole build date as "$Format:%cD"
  time_t t=time(NULL);
  struct tm *tm=localtime(&t);
//  #define GIT_COMMIT_DATE asctime(tm)
#endif

#define BUILD_DESC_FROM_COMMIT(maj,min,rev,build,commit) \
    "v" DO_STRINGIZE(maj) "." DO_STRINGIZE(min) "." DO_STRINGIZE(rev) "." DO_STRINGIZE(build) "-g" commit

#define BUILD_DESC_FROM_UNKNOWN(maj,min,rev,build) \
    "v" DO_STRINGIZE(maj) "." DO_STRINGIZE(min) "." DO_STRINGIZE(rev) "." DO_STRINGIZE(build) "-unk"

#ifndef BUILD_DESC
#    ifdef GIT_COMMIT_ID
#        define BUILD_DESC BUILD_DESC_FROM_COMMIT(DISPLAY_VERSION_MAJOR, DISPLAY_VERSION_MINOR, DISPLAY_VERSION_REVISION, DISPLAY_VERSION_BUILD, GIT_COMMIT_ID)
#    else
#        define BUILD_DESC BUILD_DESC_FROM_UNKNOWN(DISPLAY_VERSION_MAJOR, DISPLAY_VERSION_MINOR, DISPLAY_VERSION_REVISION, DISPLAY_VERSION_BUILD)
#    endif
#endif

#ifndef BUILD_DATE
#    ifdef GIT_COMMIT_DATE
#        define BUILD_DATE GIT_COMMIT_DATE
#    else
#        define BUILD_DATE __DATE__ ", " __TIME__
#    endif
#endif

const std::string CLIENT_BUILD(BUILD_DESC CLIENT_VERSION_SUFFIX);
const std::string CLIENT_DATE(BUILD_DATE);
<|endoftext|>


<commit_before>/*
    This file is part of Android File Transfer For Linux.
    Copyright (C) 2015-2018  Vladimir Menshakov

    This library is free software; you can redistribute it and/or modify it
    under the terms of the GNU Lesser General Public License as published by
    the Free Software Foundation; either version 2.1 of the License,
    or (at your option) any later version.

    This library is distributed in the hope that it will be useful, but
    WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public License
    along with this library; if not, write to the Free Software Foundation,
    Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/

#include <usb/BufferAllocator.h>
#include <usb/Device.h>
#include <Exception.h>
#include <mtp/usb/TimeoutException.h>
#include <mtp/usb/DeviceBusyException.h>
#include <mtp/usb/DeviceNotFoundException.h>
#include <mtp/ByteArray.h>
#include <mtp/log.h>

#include <sys/ioctl.h>
#include <sys/time.h>
#include <poll.h>
#include <signal.h>

#include "linux/usbdevice_fs.h"

#define IOCTL(FD, ...) do \
{ \
	int r = ioctl(FD, __VA_ARGS__); \
	if (r < 0) \
	{ \
		if (errno == EBUSY) \
			throw DeviceBusyException(FD); \
		else if (errno == ENODEV) \
			throw DeviceNotFoundException(); \
		else \
			throw posix::Exception("ioctl(" #__VA_ARGS__ ")"); \
	} \
} while(false)

namespace mtp { namespace usb
{

	InterfaceToken::InterfaceToken(int fd, unsigned interfaceNumber): _fd(fd), _interfaceNumber(interfaceNumber)
	{
		IOCTL(_fd, USBDEVFS_CLAIMINTERFACE, &interfaceNumber);
	}

	InterfaceToken::~InterfaceToken()
	{
		ioctl(_fd, USBDEVFS_RELEASEINTERFACE, &_interfaceNumber);
	}

#define PRINT_CAP(CAP, NAME) \
	if (capabilities & (CAP)) \
	{ \
		debug(NAME " "); \
		capabilities &= ~(CAP); \
	}

	Device::Device(int fd, const EndpointPtr &controlEp): _fd(fd), _capabilities(0), _controlEp(controlEp)
	{
		try
		{ IOCTL(_fd.Get(), USBDEVFS_RESET); }
		catch(const std::exception &ex)
		{ error("resetting device failed: ", ex.what()); }

		try { IOCTL(_fd.Get(), USBDEVFS_GET_CAPABILITIES, &_capabilities); }
		catch(const std::exception &ex)
		{ error("get usbfs capabilities failed: ", ex.what()); }

		debug("capabilities = 0x", hex(_capabilities, 8));
		bool mmap = _capabilities & USBDEVFS_CAP_MMAP;
		//disable mmap allocation for now, see https://github.com/whoozle/android-file-transfer-linux/issues/194
#if 1
		mmap = false;
#endif
		_bufferAllocator = std::make_shared<BufferAllocator>(mmap? fd: -1);

		if (_capabilities)
		{
			u32 capabilities = _capabilities;
			PRINT_CAP(USBDEVFS_CAP_ZERO_PACKET, "<zero-packet>");
			PRINT_CAP(USBDEVFS_CAP_BULK_CONTINUATION, "<bulk-continuation>");
			PRINT_CAP(USBDEVFS_CAP_NO_PACKET_SIZE_LIM, "<no-packet-size-limit>");
			PRINT_CAP(USBDEVFS_CAP_BULK_SCATTER_GATHER, "<bulk-scatter-gather>");
			PRINT_CAP(USBDEVFS_CAP_REAP_AFTER_DISCONNECT, "<reap-after-disconnect>");
			PRINT_CAP(USBDEVFS_CAP_MMAP, "<mmap>");
			PRINT_CAP(USBDEVFS_CAP_DROP_PRIVILEGES, "<drop-privileges>");
			if (capabilities)
				debug("<unknown capability 0x", hex(capabilities, 2), ">");
		}
		else
			debug("[none]\n");
	}

	Device::~Device()
	{ }

	int Device::GetConfiguration() const
	{
		return 0;
	}

	void Device::SetConfiguration(int idx)
	{
		error("SetConfiguration(", idx, "): not implemented");
	}

	struct Device::Urb : usbdevfs_urb, Noncopyable
	{
		static const int 		MaxBufferSize = 4096;
		BufferAllocator &		Allocator;
		int						Fd;
		int						PacketSize;
		Buffer					DataBuffer;

		Urb(BufferAllocator & allocator, int fd, u8 urbType, const EndpointPtr & ep):
			usbdevfs_urb(),
			Allocator(allocator),
			Fd(fd),
			PacketSize(ep->GetMaxPacketSize()),
			DataBuffer(Allocator.Allocate(std::max(PacketSize, MaxBufferSize / PacketSize * PacketSize)))
		{
			type			= urbType;
			endpoint		= ep->GetAddress();
			buffer			= DataBuffer.GetData();
			buffer_length	= DataBuffer.GetSize();
		}

		usbdevfs_urb *GetKernelUrb()
		{ return static_cast<usbdevfs_urb *>(this); }

		~Urb()
		{ Allocator.Free(DataBuffer); }

		size_t GetTransferSize() const
		{ return DataBuffer.GetSize(); }

		void Submit()
		{
			IOCTL(Fd, USBDEVFS_SUBMITURB, GetKernelUrb());
		}

		void Discard()
		{
			int r = ioctl(Fd, USBDEVFS_DISCARDURB, GetKernelUrb());
			if (r != 0)
			{
				perror("ioctl(USBDEVFS_DISCARDURB)");
			}
		}

		size_t Send(const IObjectInputStreamPtr &inputStream, size_t size)
		{
			if (size > DataBuffer.GetSize())
				throw std::logic_error("invalid size passed to Send");
			auto data = DataBuffer.GetData();
			size_t r = inputStream->Read(data, size);
			//HexDump("write", ByteArray(data, data + r), true);
			buffer_length = r;
			return r;
		}

		size_t Send(const ByteArray &inputData)
		{
			size_t r = std::min(DataBuffer.GetSize(), inputData.size());
			std::copy(inputData.data(), inputData.data() + r, DataBuffer.GetData());
			buffer_length = r;
			return r;
		}

		size_t Recv(const IObjectOutputStreamPtr &outputStream)
		{
			auto data = DataBuffer.GetData();
			//HexDump("read", ByteArray(data, data + actual_length), true);
			return outputStream->Write(data, actual_length);
		}

		template<unsigned Flag>
		void SetFlag(bool value)
		{
			if (value)
				flags |= Flag;
			else
				flags &= ~Flag;
		}

		void SetContinuationFlag(bool continuation)
		{ SetFlag<USBDEVFS_URB_BULK_CONTINUATION>(continuation); }

		void SetZeroPacketFlag(bool zero)
		{ SetFlag<USBDEVFS_URB_ZERO_PACKET>(zero); }
	};

	void * Device::Reap(int timeout)
	{
		auto urb = AsyncReap(); //attempt to pick up old urbs
		if (urb)
			return urb;

		timeval started = {};
		if (gettimeofday(&started, NULL) == -1)
			throw posix::Exception("gettimeofday");

		pollfd fd = {};
		fd.fd		= _fd.Get();
		fd.events	= POLLOUT | POLLWRNORM;
		int r = poll(&fd, 1, timeout);

		timeval now = {};
		if (gettimeofday(&now, NULL) == -1)
			throw posix::Exception("gettimeofday");

		if (r < 0)
			throw posix::Exception("poll");

		if (r == 0 && timeout > 0)
		{
			int ms = (now.tv_sec - started.tv_sec) * 1000 + (now.tv_usec - started.tv_usec) / 1000;
			error(ms, " ms since the last poll call");
		}
		urb = AsyncReap();
		if (urb)
			return urb;
		else
			throw TimeoutException("timeout reaping usb urb");
	}

	void * Device::AsyncReap()
	{
		usbdevfs_urb *urb;
		int r = ioctl(_fd.Get(), USBDEVFS_REAPURBNDELAY, &urb);
		if (r == 0)
			return urb;
		else if (errno == EAGAIN)
			return nullptr;
		else
			throw posix::Exception("ioctl(USBDEVFS_REAPURBNDELAY)");
	}

	void Device::ClearHalt(const EndpointPtr & ep)
	{
		try
		{ unsigned index = ep->GetAddress(); IOCTL(_fd.Get(), USBDEVFS_CLEAR_HALT, &index); }
		catch(const std::exception &ex)
		{ error("clearing halt status for ep ", hex(ep->GetAddress(), 2), ": ", ex.what()); }
	}

	void Device::Submit(Urb *urb, int timeout)
	{
		urb->Submit();
		try
		{
			while(true)
			{
				usbdevfs_urb * completedKernelUrb = static_cast<usbdevfs_urb *>(Reap(timeout));
				if (urb->GetKernelUrb() != completedKernelUrb)
				{
					error("got unknown urb: ", completedKernelUrb);
					continue;
				}
				else
					break;
			}
		}
		catch(const TimeoutException &ex)
		{
			urb->Discard();
			throw;
		}
		catch(const std::exception &ex)
		{
			error("error while submitting urb: ", ex.what());
			urb->Discard();
			throw;
		}
	}

	void Device::WriteBulk(const EndpointPtr & ep, const IObjectInputStreamPtr &inputStream, int timeout)
	{
		Urb urb(*_bufferAllocator, _fd.Get(), USBDEVFS_URB_TYPE_BULK, ep);
		size_t transferSize = urb.GetTransferSize();

		size_t r;
		bool continuation = false;
		do
		{
			r = urb.Send(inputStream, transferSize);

			if (_capabilities & USBDEVFS_CAP_ZERO_PACKET)
				urb.SetZeroPacketFlag(r != transferSize);

			if (_capabilities & USBDEVFS_CAP_BULK_CONTINUATION)
			{
				urb.SetContinuationFlag(continuation);
				continuation = true;
			}
			Submit(&urb, timeout);
		}
		while(r == transferSize);
	}

	void Device::ReadBulk(const EndpointPtr & ep, const IObjectOutputStreamPtr &outputStream, int timeout)
	{
		Urb urb(*_bufferAllocator, _fd.Get(), USBDEVFS_URB_TYPE_BULK, ep);
		size_t transferSize = urb.GetTransferSize();

		size_t r;
		bool continuation = false;
		do
		{
			if (_capabilities & USBDEVFS_CAP_BULK_CONTINUATION)
			{
				urb.SetContinuationFlag(continuation);
				continuation = true;
			}
			Submit(&urb, timeout);

			r = urb.Recv(outputStream);
		}
		while(r == transferSize);
	}

	u8 Device::TransactionType(const EndpointPtr &ep)
	{
		EndpointType type = ep->GetType();
		switch(type)
		{
		case EndpointType::Control:
			return USBDEVFS_URB_TYPE_CONTROL;
		case EndpointType::Isochronous:
			return USBDEVFS_URB_TYPE_ISO;
		case EndpointType::Bulk:
			return USBDEVFS_URB_TYPE_BULK;
		case EndpointType::Interrupt:
			return USBDEVFS_URB_TYPE_INTERRUPT;
		default:
			throw std::runtime_error("invalid endpoint type");
		}
	}

	void Device::ReadControl(u8 type, u8 req, u16 value, u16 index, ByteArray &data, int timeout)
	{
		debug("read control ", hex(type, 2), " ", hex(req, 2), " ", hex(value, 4), " ", hex(index, 4));
		usbdevfs_ctrltransfer ctrl = { };
		ctrl.bRequestType = type;
		ctrl.bRequest = req;
		ctrl.wValue = value;
		ctrl.wIndex = index;
		ctrl.wLength = data.size();
		ctrl.data = const_cast<u8 *>(data.data());
		ctrl.timeout = timeout;

		int fd = _fd.Get();

		int r = ioctl(fd, USBDEVFS_CONTROL, &ctrl);
		if (r >= 0)
			data.resize(r);
		else if (errno == EAGAIN)
			throw TimeoutException("timeout sending control transfer");
		else
			throw posix::Exception("ioctl");
	}

	void Device::WriteControl(u8 type, u8 req, u16 value, u16 index, const ByteArray &data, int timeout)
	{
		debug("write control ", hex(type, 2), " ", hex(req, 2), " ", hex(value, 4), " ", hex(index, 4));
		usbdevfs_ctrltransfer ctrl = { };
		ctrl.bRequestType = type;
		ctrl.bRequest = req;
		ctrl.wValue = value;
		ctrl.wIndex = index;
		ctrl.wLength = data.size();
		ctrl.data = const_cast<u8 *>(data.data());
		ctrl.timeout = timeout;

		int fd = _fd.Get();

		int r = ioctl(fd, USBDEVFS_CONTROL, &ctrl);
		if (r >= 0)
			return;
		else if (errno == EAGAIN)
			throw TimeoutException("timeout sending control transfer");
		else
			throw posix::Exception("ioctl");
	}

}}
<commit_msg>call gettimeofday after exception being thrown<commit_after>/*
    This file is part of Android File Transfer For Linux.
    Copyright (C) 2015-2018  Vladimir Menshakov

    This library is free software; you can redistribute it and/or modify it
    under the terms of the GNU Lesser General Public License as published by
    the Free Software Foundation; either version 2.1 of the License,
    or (at your option) any later version.

    This library is distributed in the hope that it will be useful, but
    WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public License
    along with this library; if not, write to the Free Software Foundation,
    Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/

#include <usb/BufferAllocator.h>
#include <usb/Device.h>
#include <Exception.h>
#include <mtp/usb/TimeoutException.h>
#include <mtp/usb/DeviceBusyException.h>
#include <mtp/usb/DeviceNotFoundException.h>
#include <mtp/ByteArray.h>
#include <mtp/log.h>

#include <sys/ioctl.h>
#include <sys/time.h>
#include <poll.h>
#include <signal.h>

#include "linux/usbdevice_fs.h"

#define IOCTL(FD, ...) do \
{ \
	int r = ioctl(FD, __VA_ARGS__); \
	if (r < 0) \
	{ \
		if (errno == EBUSY) \
			throw DeviceBusyException(FD); \
		else if (errno == ENODEV) \
			throw DeviceNotFoundException(); \
		else \
			throw posix::Exception("ioctl(" #__VA_ARGS__ ")"); \
	} \
} while(false)

namespace mtp { namespace usb
{

	InterfaceToken::InterfaceToken(int fd, unsigned interfaceNumber): _fd(fd), _interfaceNumber(interfaceNumber)
	{
		IOCTL(_fd, USBDEVFS_CLAIMINTERFACE, &interfaceNumber);
	}

	InterfaceToken::~InterfaceToken()
	{
		ioctl(_fd, USBDEVFS_RELEASEINTERFACE, &_interfaceNumber);
	}

#define PRINT_CAP(CAP, NAME) \
	if (capabilities & (CAP)) \
	{ \
		debug(NAME " "); \
		capabilities &= ~(CAP); \
	}

	Device::Device(int fd, const EndpointPtr &controlEp): _fd(fd), _capabilities(0), _controlEp(controlEp)
	{
		try
		{ IOCTL(_fd.Get(), USBDEVFS_RESET); }
		catch(const std::exception &ex)
		{ error("resetting device failed: ", ex.what()); }

		try { IOCTL(_fd.Get(), USBDEVFS_GET_CAPABILITIES, &_capabilities); }
		catch(const std::exception &ex)
		{ error("get usbfs capabilities failed: ", ex.what()); }

		debug("capabilities = 0x", hex(_capabilities, 8));
		bool mmap = _capabilities & USBDEVFS_CAP_MMAP;
		//disable mmap allocation for now, see https://github.com/whoozle/android-file-transfer-linux/issues/194
#if 1
		mmap = false;
#endif
		_bufferAllocator = std::make_shared<BufferAllocator>(mmap? fd: -1);

		if (_capabilities)
		{
			u32 capabilities = _capabilities;
			PRINT_CAP(USBDEVFS_CAP_ZERO_PACKET, "<zero-packet>");
			PRINT_CAP(USBDEVFS_CAP_BULK_CONTINUATION, "<bulk-continuation>");
			PRINT_CAP(USBDEVFS_CAP_NO_PACKET_SIZE_LIM, "<no-packet-size-limit>");
			PRINT_CAP(USBDEVFS_CAP_BULK_SCATTER_GATHER, "<bulk-scatter-gather>");
			PRINT_CAP(USBDEVFS_CAP_REAP_AFTER_DISCONNECT, "<reap-after-disconnect>");
			PRINT_CAP(USBDEVFS_CAP_MMAP, "<mmap>");
			PRINT_CAP(USBDEVFS_CAP_DROP_PRIVILEGES, "<drop-privileges>");
			if (capabilities)
				debug("<unknown capability 0x", hex(capabilities, 2), ">");
		}
		else
			debug("[none]\n");
	}

	Device::~Device()
	{ }

	int Device::GetConfiguration() const
	{
		return 0;
	}

	void Device::SetConfiguration(int idx)
	{
		error("SetConfiguration(", idx, "): not implemented");
	}

	struct Device::Urb : usbdevfs_urb, Noncopyable
	{
		static const int 		MaxBufferSize = 4096;
		BufferAllocator &		Allocator;
		int						Fd;
		int						PacketSize;
		Buffer					DataBuffer;

		Urb(BufferAllocator & allocator, int fd, u8 urbType, const EndpointPtr & ep):
			usbdevfs_urb(),
			Allocator(allocator),
			Fd(fd),
			PacketSize(ep->GetMaxPacketSize()),
			DataBuffer(Allocator.Allocate(std::max(PacketSize, MaxBufferSize / PacketSize * PacketSize)))
		{
			type			= urbType;
			endpoint		= ep->GetAddress();
			buffer			= DataBuffer.GetData();
			buffer_length	= DataBuffer.GetSize();
		}

		usbdevfs_urb *GetKernelUrb()
		{ return static_cast<usbdevfs_urb *>(this); }

		~Urb()
		{ Allocator.Free(DataBuffer); }

		size_t GetTransferSize() const
		{ return DataBuffer.GetSize(); }

		void Submit()
		{
			IOCTL(Fd, USBDEVFS_SUBMITURB, GetKernelUrb());
		}

		void Discard()
		{
			int r = ioctl(Fd, USBDEVFS_DISCARDURB, GetKernelUrb());
			if (r != 0)
			{
				perror("ioctl(USBDEVFS_DISCARDURB)");
			}
		}

		size_t Send(const IObjectInputStreamPtr &inputStream, size_t size)
		{
			if (size > DataBuffer.GetSize())
				throw std::logic_error("invalid size passed to Send");
			auto data = DataBuffer.GetData();
			size_t r = inputStream->Read(data, size);
			//HexDump("write", ByteArray(data, data + r), true);
			buffer_length = r;
			return r;
		}

		size_t Send(const ByteArray &inputData)
		{
			size_t r = std::min(DataBuffer.GetSize(), inputData.size());
			std::copy(inputData.data(), inputData.data() + r, DataBuffer.GetData());
			buffer_length = r;
			return r;
		}

		size_t Recv(const IObjectOutputStreamPtr &outputStream)
		{
			auto data = DataBuffer.GetData();
			//HexDump("read", ByteArray(data, data + actual_length), true);
			return outputStream->Write(data, actual_length);
		}

		template<unsigned Flag>
		void SetFlag(bool value)
		{
			if (value)
				flags |= Flag;
			else
				flags &= ~Flag;
		}

		void SetContinuationFlag(bool continuation)
		{ SetFlag<USBDEVFS_URB_BULK_CONTINUATION>(continuation); }

		void SetZeroPacketFlag(bool zero)
		{ SetFlag<USBDEVFS_URB_ZERO_PACKET>(zero); }
	};

	void * Device::Reap(int timeout)
	{
		auto urb = AsyncReap(); //attempt to pick up old urbs
		if (urb)
			return urb;

		timeval started = {};
		if (gettimeofday(&started, NULL) == -1)
			throw posix::Exception("gettimeofday");

		pollfd fd = {};
		fd.fd		= _fd.Get();
		fd.events	= POLLOUT | POLLWRNORM;
		int r = poll(&fd, 1, timeout);

		if (r < 0)
			throw posix::Exception("poll");

		timeval now = {};
		if (gettimeofday(&now, NULL) == -1)
			throw posix::Exception("gettimeofday");

		if (r == 0 && timeout > 0)
		{
			int ms = (now.tv_sec - started.tv_sec) * 1000 + (now.tv_usec - started.tv_usec) / 1000;
			error(ms, " ms since the last poll call");
		}
		urb = AsyncReap();
		if (urb)
			return urb;
		else
			throw TimeoutException("timeout reaping usb urb");
	}

	void * Device::AsyncReap()
	{
		usbdevfs_urb *urb;
		int r = ioctl(_fd.Get(), USBDEVFS_REAPURBNDELAY, &urb);
		if (r == 0)
			return urb;
		else if (errno == EAGAIN)
			return nullptr;
		else
			throw posix::Exception("ioctl(USBDEVFS_REAPURBNDELAY)");
	}

	void Device::ClearHalt(const EndpointPtr & ep)
	{
		try
		{ unsigned index = ep->GetAddress(); IOCTL(_fd.Get(), USBDEVFS_CLEAR_HALT, &index); }
		catch(const std::exception &ex)
		{ error("clearing halt status for ep ", hex(ep->GetAddress(), 2), ": ", ex.what()); }
	}

	void Device::Submit(Urb *urb, int timeout)
	{
		urb->Submit();
		try
		{
			while(true)
			{
				usbdevfs_urb * completedKernelUrb = static_cast<usbdevfs_urb *>(Reap(timeout));
				if (urb->GetKernelUrb() != completedKernelUrb)
				{
					error("got unknown urb: ", completedKernelUrb);
					continue;
				}
				else
					break;
			}
		}
		catch(const TimeoutException &ex)
		{
			urb->Discard();
			throw;
		}
		catch(const std::exception &ex)
		{
			error("error while submitting urb: ", ex.what());
			urb->Discard();
			throw;
		}
	}

	void Device::WriteBulk(const EndpointPtr & ep, const IObjectInputStreamPtr &inputStream, int timeout)
	{
		Urb urb(*_bufferAllocator, _fd.Get(), USBDEVFS_URB_TYPE_BULK, ep);
		size_t transferSize = urb.GetTransferSize();

		size_t r;
		bool continuation = false;
		do
		{
			r = urb.Send(inputStream, transferSize);

			if (_capabilities & USBDEVFS_CAP_ZERO_PACKET)
				urb.SetZeroPacketFlag(r != transferSize);

			if (_capabilities & USBDEVFS_CAP_BULK_CONTINUATION)
			{
				urb.SetContinuationFlag(continuation);
				continuation = true;
			}
			Submit(&urb, timeout);
		}
		while(r == transferSize);
	}

	void Device::ReadBulk(const EndpointPtr & ep, const IObjectOutputStreamPtr &outputStream, int timeout)
	{
		Urb urb(*_bufferAllocator, _fd.Get(), USBDEVFS_URB_TYPE_BULK, ep);
		size_t transferSize = urb.GetTransferSize();

		size_t r;
		bool continuation = false;
		do
		{
			if (_capabilities & USBDEVFS_CAP_BULK_CONTINUATION)
			{
				urb.SetContinuationFlag(continuation);
				continuation = true;
			}
			Submit(&urb, timeout);

			r = urb.Recv(outputStream);
		}
		while(r == transferSize);
	}

	u8 Device::TransactionType(const EndpointPtr &ep)
	{
		EndpointType type = ep->GetType();
		switch(type)
		{
		case EndpointType::Control:
			return USBDEVFS_URB_TYPE_CONTROL;
		case EndpointType::Isochronous:
			return USBDEVFS_URB_TYPE_ISO;
		case EndpointType::Bulk:
			return USBDEVFS_URB_TYPE_BULK;
		case EndpointType::Interrupt:
			return USBDEVFS_URB_TYPE_INTERRUPT;
		default:
			throw std::runtime_error("invalid endpoint type");
		}
	}

	void Device::ReadControl(u8 type, u8 req, u16 value, u16 index, ByteArray &data, int timeout)
	{
		debug("read control ", hex(type, 2), " ", hex(req, 2), " ", hex(value, 4), " ", hex(index, 4));
		usbdevfs_ctrltransfer ctrl = { };
		ctrl.bRequestType = type;
		ctrl.bRequest = req;
		ctrl.wValue = value;
		ctrl.wIndex = index;
		ctrl.wLength = data.size();
		ctrl.data = const_cast<u8 *>(data.data());
		ctrl.timeout = timeout;

		int fd = _fd.Get();

		int r = ioctl(fd, USBDEVFS_CONTROL, &ctrl);
		if (r >= 0)
			data.resize(r);
		else if (errno == EAGAIN)
			throw TimeoutException("timeout sending control transfer");
		else
			throw posix::Exception("ioctl");
	}

	void Device::WriteControl(u8 type, u8 req, u16 value, u16 index, const ByteArray &data, int timeout)
	{
		debug("write control ", hex(type, 2), " ", hex(req, 2), " ", hex(value, 4), " ", hex(index, 4));
		usbdevfs_ctrltransfer ctrl = { };
		ctrl.bRequestType = type;
		ctrl.bRequest = req;
		ctrl.wValue = value;
		ctrl.wIndex = index;
		ctrl.wLength = data.size();
		ctrl.data = const_cast<u8 *>(data.data());
		ctrl.timeout = timeout;

		int fd = _fd.Get();

		int r = ioctl(fd, USBDEVFS_CONTROL, &ctrl);
		if (r >= 0)
			return;
		else if (errno == EAGAIN)
			throw TimeoutException("timeout sending control transfer");
		else
			throw posix::Exception("ioctl");
	}

}}
<|endoftext|>


<commit_before>/*
<License>
Copyright 2015 Virtium Technology

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.
</License>
*/

#include <assert.h>

#include "AtaProtocolEssense1.h"

#include "ProtocolAtaPassThrough.h"

namespace vtStor
{
namespace Protocol
{

    const vtStor::U8 FEATURE_REGISTER_OFFSET = 0;
    const vtStor::U8 ERROR_REGISTER_OFFSET = 0;
    const vtStor::U8 COUNT_REGISTER_OFFSET = 1;
    const vtStor::U8 LBA_LOW_REGISTER_OFFSET = 2;
    const vtStor::U8 LBA_MID_REGISTER_OFFSET = 3;
    const vtStor::U8 LBA_HIGH_REGISTER_OFFSET = 4;
    const vtStor::U8 DEVICE_REGISTER_OFFSET = 5;
    const vtStor::U8 COMMAND_REGISTER_OFFSET = 6;
    const vtStor::U8 STATUS_REGISTER_OFFSET = 6;
    const vtStor::U8 RESERVED_REGISTER_OFFSET = 7;

    eErrorCode cAtaPassThrough::IssueCommand( std::shared_ptr<cBufferInterface> Essense, std::shared_ptr<cBufferInterface> DataBuffer )
    {
        eErrorCode errorCode = eErrorCode::None;

        cEssenseAta1 essense = cEssenseAta1::Reader( Essense );

        switch (essense.GetHeader().Format)
        {
            case 1:
            {
                m_DeviceHandle = essense.GetDeviceHandle();

                InitializePassThroughDirect(
                    essense.GetCommandCharacteristics(),
                    essense.GetTaskFileExt(),
                    essense.GetTaskFile(),
                    DataBuffer,
                    60 //TODO: allow configurable timeout
                    );

                U32 bytesReturned = 0;
                errorCode = IssuePassThroughDirectCommand(bytesReturned);
            } break;

            default:
                errorCode = eErrorCode::FormatNotSupported;
                break;
        }

        return(errorCode);
    }

    void cAtaPassThrough::InitializePassThroughDirect( const StorageUtility::Ata::sCommandCharacteristic& CommandCharacteristics, const StorageUtility::Ata::uTaskFileRegister& PreviousTaskFile, const StorageUtility::Ata::uTaskFileRegister& CurrentTaskFile, std::shared_ptr<cBufferInterface> DataBuffer, U32 TimeoutValueInSeconds )
    {
        m_AtaPassThrough.Length = sizeof( ATA_PASS_THROUGH_DIRECT );
        m_AtaPassThrough.DataTransferLength = CommandCharacteristics.DataTransferLengthInBytes;
        m_AtaPassThrough.TimeOutValue = TimeoutValueInSeconds;
        if (nullptr != DataBuffer)
        {
            m_AtaPassThrough.DataBuffer = DataBuffer->ToDataBuffer();
        }
        m_AtaPassThrough.ReservedAsUchar = 0;
        m_AtaPassThrough.ReservedAsUlong = 0;

        InitializeFlags( CommandCharacteristics );
        InitializeTaskFileInputRegisters( PreviousTaskFile, CurrentTaskFile );
    }

    void cAtaPassThrough::InitializeFlags( const StorageUtility::Ata::sCommandCharacteristic& AtaCommandCharacteristic )
    {
        // Clear all flags
        m_AtaPassThrough.AtaFlags = 0;

        if (StorageUtility::Ata::eDeviceReadyFlag::DEVICE_READY_REQUIRED == AtaCommandCharacteristic.DeviceReadyFlag)
        {
            m_AtaPassThrough.AtaFlags |= ATA_FLAGS_DRDY_REQUIRED;
        }

        switch (AtaCommandCharacteristic.DataAccess)
        {
        case StorageUtility::Ata::eDataAccess::READ_FROM_DEVICE:
        {
            m_AtaPassThrough.AtaFlags |= ATA_FLAGS_DATA_IN;
        } break;
        case StorageUtility::Ata::eDataAccess::WRITE_TO_DEVICE:
        {
            m_AtaPassThrough.AtaFlags |= ATA_FLAGS_DATA_OUT;
        } break;
        }

        if (StorageUtility::Ata::eFieldFormatting::COMMAND_48_BIT == AtaCommandCharacteristic.FieldFormatting)
        {
            m_AtaPassThrough.AtaFlags |= ATA_FLAGS_48BIT_COMMAND;
        }

        if (StorageUtility::Ata::eTransferMode::DMA_PROTOCOL == AtaCommandCharacteristic.TransferMode)
        {
            m_AtaPassThrough.AtaFlags |= ATA_FLAGS_USE_DMA;
        }

        if (StorageUtility::Ata::eMultipleMode::NOT_MULTIPLE_COMMAND == AtaCommandCharacteristic.MultipleMode)
        {
            m_AtaPassThrough.AtaFlags |= ATA_FLAGS_NO_MULTIPLE;
        }
    }

    void cAtaPassThrough::InitializeTaskFileInputRegisters( const StorageUtility::Ata::uTaskFileRegister& PreviousTaskFile, const StorageUtility::Ata::uTaskFileRegister& CurrentTaskFile )
    {
        m_AtaPassThrough.PreviousTaskFile[FEATURE_REGISTER_OFFSET] = PreviousTaskFile.InputRegister.Feature;
        m_AtaPassThrough.PreviousTaskFile[COUNT_REGISTER_OFFSET] = PreviousTaskFile.InputRegister.Count;
        m_AtaPassThrough.PreviousTaskFile[LBA_LOW_REGISTER_OFFSET] = PreviousTaskFile.InputRegister.LbaLow;
        m_AtaPassThrough.PreviousTaskFile[LBA_MID_REGISTER_OFFSET] = PreviousTaskFile.InputRegister.LbaMid;
        m_AtaPassThrough.PreviousTaskFile[LBA_HIGH_REGISTER_OFFSET] = PreviousTaskFile.InputRegister.LbaHigh;
        m_AtaPassThrough.PreviousTaskFile[DEVICE_REGISTER_OFFSET] = PreviousTaskFile.InputRegister.Device;
        m_AtaPassThrough.PreviousTaskFile[COMMAND_REGISTER_OFFSET] = PreviousTaskFile.InputRegister.Command;
        m_AtaPassThrough.PreviousTaskFile[RESERVED_REGISTER_OFFSET] = PreviousTaskFile.InputRegister.Reserved;

        m_AtaPassThrough.CurrentTaskFile[FEATURE_REGISTER_OFFSET] = CurrentTaskFile.InputRegister.Feature;
        m_AtaPassThrough.CurrentTaskFile[COUNT_REGISTER_OFFSET] = CurrentTaskFile.InputRegister.Count;
        m_AtaPassThrough.CurrentTaskFile[LBA_LOW_REGISTER_OFFSET] = CurrentTaskFile.InputRegister.LbaLow;
        m_AtaPassThrough.CurrentTaskFile[LBA_MID_REGISTER_OFFSET] = CurrentTaskFile.InputRegister.LbaMid;
        m_AtaPassThrough.CurrentTaskFile[LBA_HIGH_REGISTER_OFFSET] = CurrentTaskFile.InputRegister.LbaHigh;
        m_AtaPassThrough.CurrentTaskFile[DEVICE_REGISTER_OFFSET] = CurrentTaskFile.InputRegister.Device;
        m_AtaPassThrough.CurrentTaskFile[COMMAND_REGISTER_OFFSET] = CurrentTaskFile.InputRegister.Command;
        m_AtaPassThrough.CurrentTaskFile[RESERVED_REGISTER_OFFSET] = CurrentTaskFile.InputRegister.Reserved;
    }

    eErrorCode cAtaPassThrough::IssuePassThroughDirectCommand( U32& BytesReturned )
    {

        assert( INVALID_HANDLE_VALUE != m_DeviceHandle );

        eErrorCode error;
        error = eErrorCode::None;

        BOOL commandSuccessfulFlag;
        DWORD bytesReturned;
        commandSuccessfulFlag = DeviceIoControl
            (
            m_DeviceHandle,
            IOCTL_ATA_PASS_THROUGH_DIRECT,
            &m_AtaPassThrough,
            m_AtaPassThrough.Length,
            &m_AtaPassThrough,
            m_AtaPassThrough.Length,
            &bytesReturned,
            NULL
            );

        // If the operation was not successful:
        if (FALSE == commandSuccessfulFlag)
        {
            error = eErrorCode::Io;

            //TODO: report extended error
            //fprintf( stderr, "\nDeviceIoControl was not successful. Error Code: %d", GetLastError() );
        }

        BytesReturned = bytesReturned;

        return(error);
    }

}
}

VT_STOR_ATA_PROTOCOL_API void vtStorProtocolAtaPassThroughInit(std::shared_ptr<vtStor::Protocol::cProtocolInterface>& Protocol)
{
    Protocol = std::make_shared<vtStor::Protocol::cAtaPassThrough>();
}<commit_msg>Check header of Essense before create Essense object<commit_after>/*
<License>
Copyright 2015 Virtium Technology

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.
</License>
*/

#include <assert.h>

#include "AtaProtocolEssense1.h"

#include "ProtocolAtaPassThrough.h"

namespace vtStor
{
namespace Protocol
{

    const vtStor::U8 FEATURE_REGISTER_OFFSET = 0;
    const vtStor::U8 ERROR_REGISTER_OFFSET = 0;
    const vtStor::U8 COUNT_REGISTER_OFFSET = 1;
    const vtStor::U8 LBA_LOW_REGISTER_OFFSET = 2;
    const vtStor::U8 LBA_MID_REGISTER_OFFSET = 3;
    const vtStor::U8 LBA_HIGH_REGISTER_OFFSET = 4;
    const vtStor::U8 DEVICE_REGISTER_OFFSET = 5;
    const vtStor::U8 COMMAND_REGISTER_OFFSET = 6;
    const vtStor::U8 STATUS_REGISTER_OFFSET = 6;
    const vtStor::U8 RESERVED_REGISTER_OFFSET = 7;

    eErrorCode cAtaPassThrough::IssueCommand( std::shared_ptr<cBufferInterface> Essense, std::shared_ptr<cBufferInterface> DataBuffer )
    {
        eErrorCode errorCode = eErrorCode::None;

        cBufferFormatter bufferFormatter = cBufferFormatter::Reader(Essense);

        switch (bufferFormatter.GetHeader().Format)
        {
            case 1:
            {
                cEssenseAta1 essense = cEssenseAta1::Reader(Essense);
                m_DeviceHandle = essense.GetDeviceHandle();

                InitializePassThroughDirect(
                    essense.GetCommandCharacteristics(),
                    essense.GetTaskFileExt(),
                    essense.GetTaskFile(),
                    DataBuffer,
                    60 //TODO: allow configurable timeout
                    );

                U32 bytesReturned = 0;
                errorCode = IssuePassThroughDirectCommand(bytesReturned);
            } break;

            default:
                errorCode = eErrorCode::FormatNotSupported;
                break;
        }

        return(errorCode);
    }

    void cAtaPassThrough::InitializePassThroughDirect( const StorageUtility::Ata::sCommandCharacteristic& CommandCharacteristics, const StorageUtility::Ata::uTaskFileRegister& PreviousTaskFile, const StorageUtility::Ata::uTaskFileRegister& CurrentTaskFile, std::shared_ptr<cBufferInterface> DataBuffer, U32 TimeoutValueInSeconds )
    {
        m_AtaPassThrough.Length = sizeof( ATA_PASS_THROUGH_DIRECT );
        m_AtaPassThrough.DataTransferLength = CommandCharacteristics.DataTransferLengthInBytes;
        m_AtaPassThrough.TimeOutValue = TimeoutValueInSeconds;
        if (nullptr != DataBuffer)
        {
            m_AtaPassThrough.DataBuffer = DataBuffer->ToDataBuffer();
        }
        m_AtaPassThrough.ReservedAsUchar = 0;
        m_AtaPassThrough.ReservedAsUlong = 0;

        InitializeFlags( CommandCharacteristics );
        InitializeTaskFileInputRegisters( PreviousTaskFile, CurrentTaskFile );
    }

    void cAtaPassThrough::InitializeFlags( const StorageUtility::Ata::sCommandCharacteristic& AtaCommandCharacteristic )
    {
        // Clear all flags
        m_AtaPassThrough.AtaFlags = 0;

        if (StorageUtility::Ata::eDeviceReadyFlag::DEVICE_READY_REQUIRED == AtaCommandCharacteristic.DeviceReadyFlag)
        {
            m_AtaPassThrough.AtaFlags |= ATA_FLAGS_DRDY_REQUIRED;
        }

        switch (AtaCommandCharacteristic.DataAccess)
        {
        case StorageUtility::Ata::eDataAccess::READ_FROM_DEVICE:
        {
            m_AtaPassThrough.AtaFlags |= ATA_FLAGS_DATA_IN;
        } break;
        case StorageUtility::Ata::eDataAccess::WRITE_TO_DEVICE:
        {
            m_AtaPassThrough.AtaFlags |= ATA_FLAGS_DATA_OUT;
        } break;
        }

        if (StorageUtility::Ata::eFieldFormatting::COMMAND_48_BIT == AtaCommandCharacteristic.FieldFormatting)
        {
            m_AtaPassThrough.AtaFlags |= ATA_FLAGS_48BIT_COMMAND;
        }

        if (StorageUtility::Ata::eTransferMode::DMA_PROTOCOL == AtaCommandCharacteristic.TransferMode)
        {
            m_AtaPassThrough.AtaFlags |= ATA_FLAGS_USE_DMA;
        }

        if (StorageUtility::Ata::eMultipleMode::NOT_MULTIPLE_COMMAND == AtaCommandCharacteristic.MultipleMode)
        {
            m_AtaPassThrough.AtaFlags |= ATA_FLAGS_NO_MULTIPLE;
        }
    }

    void cAtaPassThrough::InitializeTaskFileInputRegisters( const StorageUtility::Ata::uTaskFileRegister& PreviousTaskFile, const StorageUtility::Ata::uTaskFileRegister& CurrentTaskFile )
    {
        m_AtaPassThrough.PreviousTaskFile[FEATURE_REGISTER_OFFSET] = PreviousTaskFile.InputRegister.Feature;
        m_AtaPassThrough.PreviousTaskFile[COUNT_REGISTER_OFFSET] = PreviousTaskFile.InputRegister.Count;
        m_AtaPassThrough.PreviousTaskFile[LBA_LOW_REGISTER_OFFSET] = PreviousTaskFile.InputRegister.LbaLow;
        m_AtaPassThrough.PreviousTaskFile[LBA_MID_REGISTER_OFFSET] = PreviousTaskFile.InputRegister.LbaMid;
        m_AtaPassThrough.PreviousTaskFile[LBA_HIGH_REGISTER_OFFSET] = PreviousTaskFile.InputRegister.LbaHigh;
        m_AtaPassThrough.PreviousTaskFile[DEVICE_REGISTER_OFFSET] = PreviousTaskFile.InputRegister.Device;
        m_AtaPassThrough.PreviousTaskFile[COMMAND_REGISTER_OFFSET] = PreviousTaskFile.InputRegister.Command;
        m_AtaPassThrough.PreviousTaskFile[RESERVED_REGISTER_OFFSET] = PreviousTaskFile.InputRegister.Reserved;

        m_AtaPassThrough.CurrentTaskFile[FEATURE_REGISTER_OFFSET] = CurrentTaskFile.InputRegister.Feature;
        m_AtaPassThrough.CurrentTaskFile[COUNT_REGISTER_OFFSET] = CurrentTaskFile.InputRegister.Count;
        m_AtaPassThrough.CurrentTaskFile[LBA_LOW_REGISTER_OFFSET] = CurrentTaskFile.InputRegister.LbaLow;
        m_AtaPassThrough.CurrentTaskFile[LBA_MID_REGISTER_OFFSET] = CurrentTaskFile.InputRegister.LbaMid;
        m_AtaPassThrough.CurrentTaskFile[LBA_HIGH_REGISTER_OFFSET] = CurrentTaskFile.InputRegister.LbaHigh;
        m_AtaPassThrough.CurrentTaskFile[DEVICE_REGISTER_OFFSET] = CurrentTaskFile.InputRegister.Device;
        m_AtaPassThrough.CurrentTaskFile[COMMAND_REGISTER_OFFSET] = CurrentTaskFile.InputRegister.Command;
        m_AtaPassThrough.CurrentTaskFile[RESERVED_REGISTER_OFFSET] = CurrentTaskFile.InputRegister.Reserved;
    }

    eErrorCode cAtaPassThrough::IssuePassThroughDirectCommand( U32& BytesReturned )
    {

        assert( INVALID_HANDLE_VALUE != m_DeviceHandle );

        eErrorCode error;
        error = eErrorCode::None;

        BOOL commandSuccessfulFlag;
        DWORD bytesReturned;
        commandSuccessfulFlag = DeviceIoControl
            (
            m_DeviceHandle,
            IOCTL_ATA_PASS_THROUGH_DIRECT,
            &m_AtaPassThrough,
            m_AtaPassThrough.Length,
            &m_AtaPassThrough,
            m_AtaPassThrough.Length,
            &bytesReturned,
            NULL
            );

        // If the operation was not successful:
        if (FALSE == commandSuccessfulFlag)
        {
            error = eErrorCode::Io;

            //TODO: report extended error
            //fprintf( stderr, "\nDeviceIoControl was not successful. Error Code: %d", GetLastError() );
        }

        BytesReturned = bytesReturned;

        return(error);
    }

}
}

VT_STOR_ATA_PROTOCOL_API void vtStorProtocolAtaPassThroughInit(std::shared_ptr<vtStor::Protocol::cProtocolInterface>& Protocol)
{
    Protocol = std::make_shared<vtStor::Protocol::cAtaPassThrough>();
}<|endoftext|>


<commit_before>#include "Core\Context.h"
#include "Core\Engine.h"

using namespace Mile;

int main( )
{
   auto context = std::make_unique<Context>( );
   auto engine = new Engine( context.get( ) );

   if ( !engine->Init( ) )
   {
      return 1;
   }

   int execute = engine->Execute( );
   context.reset( );
   return execute;
}<commit_msg>Fxied Component Register<commit_after>#include "Core\Context.h"
#include "Core\Engine.h"
#include "Core\World.h"
#include "Core\Entity.h"
#include "Component\CameraComponent.h"
#include "Component\MeshRenderComponent.h"
#include "Component\LightComponent.h"
#include "Resource\ResourceManager.h"
#include "Resource\Model.h"
#include "Resource\ModelLoader.h"
#include "Resource\Material.h"
#include "Resource\Texture2D.h"

using namespace Mile;

int main( )
{
   auto context = std::make_unique<Context>( );
   auto engine = new Engine( context.get( ) );

   if ( !engine->Init( ) )
   {
      return 1;
   }

   auto world = context->GetSubSystem<World>( );
   auto resMng = context->GetSubSystem<ResourceManager>( );

   auto camera = world->CreateEntity( TEXT( "Camera" ) );
   auto camComp = camera->AddComponent<CameraComponent>( );
   auto camTransform = camera->GetTransform( );
   camTransform->SetPosition( Vector3( 0.0f, 0.0f, -100.0f ) );

   // Camera setup

   auto light = world->CreateEntity( TEXT( "DirectionalLight" ) );
   auto lightComp = camera->AddComponent<LightComponent>( );

   // Light setup

   auto model = resMng->Load<Model>( TEXT( "Contents/Models/dragon.obj" ) );
   auto modelEntity = Model::Instantiate( model, world );
   auto modelMeshRenderer = modelEntity->GetComponent<MeshRenderComponent>( );
   auto mat = modelMeshRenderer->GetMaterial( );

   auto texture = resMng->Load<Texture2D>( TEXT( "Contents/Textures/test.png" ) );
   mat->SetDiffuseMap( texture );

   // Model setup

   int execute = engine->Execute( );
   SafeDelete( engine );
   return execute;
}<|endoftext|>


<commit_before>/*************************************************************************
*    UrBackup - Client/Server backup system
*    Copyright (C) 2011-2016 Martin Raiber
*
*    This program is free software: you can redistribute it and/or modify
*    it under the terms of the GNU Affero General Public License as published by
*    the Free Software Foundation, either version 3 of the License, or
*    (at your option) any later version.
*
*    This program is distributed in the hope that it will be useful,
*    but WITHOUT ANY WARRANTY; without even the implied warranty of
*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*    GNU Affero General Public License for more details.
*
*    You should have received a copy of the GNU Affero General Public License
*    along with this program.  If not, see <http://www.gnu.org/licenses/>.
**************************************************************************/

#include "Interface/Thread.h"

#include "ThreadPool.h"
#include "Server.h"
#include "stringtools.h"

const unsigned int max_waiting_threads=2;

CPoolThread::CPoolThread(CThreadPool *pMgr)
{
	mgr=pMgr;
	dexit=false;
}

void CPoolThread::operator()(void)
{
	THREAD_ID tid = Server->getThreadID();
	THREADPOOL_TICKET ticket;
	bool stop=false;
	std::string name;
	IThread *tr=mgr->getRunnable(&ticket, false, stop, name);
	if(tr!=NULL)
	{
		if (!name.empty())
		{
			Server->setCurrentThreadName(name);
		}
		else
		{
			Server->setCurrentThreadName("unnamed");
		}
		(*tr)();
		Server->clearDatabases(tid);
	}

	if(!stop)
	{
		while(dexit==false)
		{
			stop=false;
			std::string name;
			IThread *tr=mgr->getRunnable(&ticket, true, stop, name);
			if(tr!=NULL)
			{
				if (!name.empty())
				{
					Server->setCurrentThreadName(name);
				}
				else
				{
					Server->setCurrentThreadName("unnamed");
				}
				(*tr)();
				Server->clearDatabases(tid);
			}
			else if(stop)
			{
				break;
			}
		}
	}
	Server->destroyDatabases(tid);
	mgr->Remove(this);
	delete this;
}

void CPoolThread::shutdown(void)
{
	dexit=true;
}

IThread * CThreadPool::getRunnable(THREADPOOL_TICKET *todel, bool del, bool& stop, std::string& name)
{
	IScopedLock lock(mutex);

	if( del==true )
	{
		--nRunning;
		std::map<THREADPOOL_TICKET, ICondition *>::iterator it=running.find(*todel);
		if( it!=running.end() )
		{
			if( it->second!=NULL )
				it->second->notify_all();

			running.erase(it);
		}
	}

	IThread *ret=NULL;
	while(ret==NULL && dexit==false)
	{
		if( toexecute.size()==0)
		{
			if(nThreads-nRunning>max_waiting_threads)
			{
				stop=true;
				return NULL;
			}
			Server->setCurrentThreadName("idle pool thread");
			cond->wait(&lock);
		}
		else
		{
			ret=toexecute[0].runnable;
			*todel=toexecute[0].ticket;
			name = toexecute[0].name;
			toexecute.erase( toexecute.begin() );
		}
	}
	return ret;
}

void CThreadPool::Remove(CPoolThread *pt)
{
	IScopedLock lock(mutex);
	for(size_t i=0;i<threads.size();++i)
	{
		if( threads[i]==pt )
		{
			threads.erase( threads.begin()+i);
			--nThreads;
			return;
		}
	}
}

CThreadPool::CThreadPool()
{
	nRunning=0;
	nThreads=0;
	currticket=0;
	dexit=false;

	mutex=Server->createMutex();
	cond=Server->createCondition();
}

CThreadPool::~CThreadPool()
{
	delete mutex;
	delete cond;
}

void CThreadPool::Shutdown(void)
{
	bool do_leak_check=(Server->getServerParameter("leak_check")=="true");
	IScopedLock lock(mutex);
	for(size_t i=0;i<threads.size();++i)
	{
		threads[i]->shutdown();
	}
	dexit=true;

	unsigned int max=0;
	while(threads.size()>0 )
	{
		lock.relock(NULL);
		cond->notify_all();
		Server->wait(100);
		lock.relock(mutex);

		//wait for max 300 msec
		if( (!do_leak_check && max>=3) || (do_leak_check && max>=30) )
		{
			Server->Log("Maximum wait time for thread pool exceeded. Shutting down the hard way", LL_ERROR);
			break;
		}
		++max;
	}
}

bool CThreadPool::isRunningInt(THREADPOOL_TICKET ticket)
{
	std::map<THREADPOOL_TICKET, ICondition*>::iterator it=running.find(ticket);
	if( it!=running.end() )
		return true;
	else
		return false;
}

bool CThreadPool::isRunning(THREADPOOL_TICKET ticket)
{
	IScopedLock lock(mutex);
	return isRunningInt(ticket);
}

bool CThreadPool::waitFor(std::vector<THREADPOOL_TICKET> tickets, int timems)
{
	int64 starttime;
	if(timems>=0)
	{
		starttime = Server->getTimeMS();
	}

	IScopedLock lock(mutex);
	ICondition *cond=Server->createCondition();

	for( size_t i=0;i<tickets.size();++i)
	{
		std::map<THREADPOOL_TICKET, ICondition*>::iterator it=running.find(tickets[i]);
		if( it!=running.end() )
		{
			it->second=cond;
		}
	}

	bool ret=false;

	while(true)
	{
		bool r=false;
		for(size_t i=0;i<tickets.size();++i)
		{
			if( isRunningInt(tickets[i]) )
			{
				r=true;
				break;
			}
		}

		if( r==false )
		{
			ret = true;
			break;
		}

		cond->wait(&lock, timems);

		if(timems>=0)
		{
			int64 ctime = Server->getTimeMS();
			if(ctime-starttime>timems)
			{
				break;
			}
		}
	}

	for( size_t i=0;i<tickets.size();++i)
	{
		std::map<THREADPOOL_TICKET, ICondition*>::iterator it=running.find(tickets[i]);
		if( it!=running.end() )
		{
			if(it->second==cond)
			{
				it->second=NULL;
			}
		}
	}

	Server->destroy(cond);

	return ret;
}

THREADPOOL_TICKET CThreadPool::execute(IThread *runnable, const std::string& name)
{
	IScopedLock lock(mutex);
	if( nThreads-nRunning==0 )
	{
		CPoolThread *nt=new CPoolThread(this);
		Server->createThread(nt);
		++nThreads;
		threads.push_back(nt);
	}

	toexecute.push_back(SNewTask(runnable, ++currticket, name));
	running.insert(std::pair<THREADPOOL_TICKET, ICondition*>(currticket, (ICondition*)NULL) );
	++nRunning;
	cond->notify_one();
	return currticket;
}

void CThreadPool::executeWait(IThread *runnable, const std::string& name)
{
	THREADPOOL_TICKET ticket=execute(runnable, name);
	waitFor(ticket);
}

bool CThreadPool::waitFor(THREADPOOL_TICKET ticket, int timems)
{
	std::vector<THREADPOOL_TICKET> t;
	t.push_back(ticket);
	return waitFor(t, timems);
}

<commit_msg>Check waitFor timeout before condition wait<commit_after>/*************************************************************************
*    UrBackup - Client/Server backup system
*    Copyright (C) 2011-2016 Martin Raiber
*
*    This program is free software: you can redistribute it and/or modify
*    it under the terms of the GNU Affero General Public License as published by
*    the Free Software Foundation, either version 3 of the License, or
*    (at your option) any later version.
*
*    This program is distributed in the hope that it will be useful,
*    but WITHOUT ANY WARRANTY; without even the implied warranty of
*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*    GNU Affero General Public License for more details.
*
*    You should have received a copy of the GNU Affero General Public License
*    along with this program.  If not, see <http://www.gnu.org/licenses/>.
**************************************************************************/

#include "Interface/Thread.h"

#include "ThreadPool.h"
#include "Server.h"
#include "stringtools.h"

const unsigned int max_waiting_threads=2;

CPoolThread::CPoolThread(CThreadPool *pMgr)
{
	mgr=pMgr;
	dexit=false;
}

void CPoolThread::operator()(void)
{
	THREAD_ID tid = Server->getThreadID();
	THREADPOOL_TICKET ticket;
	bool stop=false;
	std::string name;
	IThread *tr=mgr->getRunnable(&ticket, false, stop, name);
	if(tr!=NULL)
	{
		if (!name.empty())
		{
			Server->setCurrentThreadName(name);
		}
		else
		{
			Server->setCurrentThreadName("unnamed");
		}
		(*tr)();
		Server->clearDatabases(tid);
	}

	if(!stop)
	{
		while(dexit==false)
		{
			stop=false;
			std::string name;
			IThread *tr=mgr->getRunnable(&ticket, true, stop, name);
			if(tr!=NULL)
			{
				if (!name.empty())
				{
					Server->setCurrentThreadName(name);
				}
				else
				{
					Server->setCurrentThreadName("unnamed");
				}
				(*tr)();
				Server->clearDatabases(tid);
			}
			else if(stop)
			{
				break;
			}
		}
	}
	Server->destroyDatabases(tid);
	mgr->Remove(this);
	delete this;
}

void CPoolThread::shutdown(void)
{
	dexit=true;
}

IThread * CThreadPool::getRunnable(THREADPOOL_TICKET *todel, bool del, bool& stop, std::string& name)
{
	IScopedLock lock(mutex);

	if( del==true )
	{
		--nRunning;
		std::map<THREADPOOL_TICKET, ICondition *>::iterator it=running.find(*todel);
		if( it!=running.end() )
		{
			if( it->second!=NULL )
				it->second->notify_all();

			running.erase(it);
		}
	}

	IThread *ret=NULL;
	while(ret==NULL && dexit==false)
	{
		if( toexecute.size()==0)
		{
			if(nThreads-nRunning>max_waiting_threads)
			{
				stop=true;
				return NULL;
			}
			Server->setCurrentThreadName("idle pool thread");
			cond->wait(&lock);
		}
		else
		{
			ret=toexecute[0].runnable;
			*todel=toexecute[0].ticket;
			name = toexecute[0].name;
			toexecute.erase( toexecute.begin() );
		}
	}
	return ret;
}

void CThreadPool::Remove(CPoolThread *pt)
{
	IScopedLock lock(mutex);
	for(size_t i=0;i<threads.size();++i)
	{
		if( threads[i]==pt )
		{
			threads.erase( threads.begin()+i);
			--nThreads;
			return;
		}
	}
}

CThreadPool::CThreadPool()
{
	nRunning=0;
	nThreads=0;
	currticket=0;
	dexit=false;

	mutex=Server->createMutex();
	cond=Server->createCondition();
}

CThreadPool::~CThreadPool()
{
	delete mutex;
	delete cond;
}

void CThreadPool::Shutdown(void)
{
	bool do_leak_check=(Server->getServerParameter("leak_check")=="true");
	IScopedLock lock(mutex);
	for(size_t i=0;i<threads.size();++i)
	{
		threads[i]->shutdown();
	}
	dexit=true;

	unsigned int max=0;
	while(threads.size()>0 )
	{
		lock.relock(NULL);
		cond->notify_all();
		Server->wait(100);
		lock.relock(mutex);

		//wait for max 300 msec
		if( (!do_leak_check && max>=3) || (do_leak_check && max>=30) )
		{
			Server->Log("Maximum wait time for thread pool exceeded. Shutting down the hard way", LL_ERROR);
			break;
		}
		++max;
	}
}

bool CThreadPool::isRunningInt(THREADPOOL_TICKET ticket)
{
	std::map<THREADPOOL_TICKET, ICondition*>::iterator it=running.find(ticket);
	if( it!=running.end() )
		return true;
	else
		return false;
}

bool CThreadPool::isRunning(THREADPOOL_TICKET ticket)
{
	IScopedLock lock(mutex);
	return isRunningInt(ticket);
}

bool CThreadPool::waitFor(std::vector<THREADPOOL_TICKET> tickets, int timems)
{
	int64 starttime;
	if(timems>=0)
	{
		starttime = Server->getTimeMS();
	}

	IScopedLock lock(mutex);
	ICondition *cond=Server->createCondition();

	for( size_t i=0;i<tickets.size();++i)
	{
		std::map<THREADPOOL_TICKET, ICondition*>::iterator it=running.find(tickets[i]);
		if( it!=running.end() )
		{
			it->second=cond;
		}
	}

	bool ret=false;

	while(true)
	{
		bool r=false;
		for(size_t i=0;i<tickets.size();++i)
		{
			if( isRunningInt(tickets[i]) )
			{
				r=true;
				break;
			}
		}

		if( r==false )
		{
			ret = true;
			break;
		}

		if (timems >= 0)
		{
			int64 ctime = Server->getTimeMS();
			if (ctime - starttime>=timems)
			{
				break;
			}
		}

		cond->wait(&lock, timems);
	}

	for( size_t i=0;i<tickets.size();++i)
	{
		std::map<THREADPOOL_TICKET, ICondition*>::iterator it=running.find(tickets[i]);
		if( it!=running.end() )
		{
			if(it->second==cond)
			{
				it->second=NULL;
			}
		}
	}

	Server->destroy(cond);

	return ret;
}

THREADPOOL_TICKET CThreadPool::execute(IThread *runnable, const std::string& name)
{
	IScopedLock lock(mutex);
	if( nThreads-nRunning==0 )
	{
		CPoolThread *nt=new CPoolThread(this);
		Server->createThread(nt);
		++nThreads;
		threads.push_back(nt);
	}

	toexecute.push_back(SNewTask(runnable, ++currticket, name));
	running.insert(std::pair<THREADPOOL_TICKET, ICondition*>(currticket, (ICondition*)NULL) );
	++nRunning;
	cond->notify_one();
	return currticket;
}

void CThreadPool::executeWait(IThread *runnable, const std::string& name)
{
	THREADPOOL_TICKET ticket=execute(runnable, name);
	waitFor(ticket);
}

bool CThreadPool::waitFor(THREADPOOL_TICKET ticket, int timems)
{
	std::vector<THREADPOOL_TICKET> t;
	t.push_back(ticket);
	return waitFor(t, timems);
}

<|endoftext|>


<commit_before>/**
 * Appcelerator Titanium Mobile
 * Copyright (c) 2009-2012 by Appcelerator, Inc. All Rights Reserved.
 * Licensed under the terms of the Apache Public License
 * Please see the LICENSE included with this distribution for details.
 */

#include "TiUIPicker.h"
#include "TiGenericFunctionObject.h"

TiUIPicker::TiUIPicker(NativeObjectFactory* nativeObjectFactory)
    : TiUIBase(nativeObjectFactory, "")
{
}

TiUIPicker::~TiUIPicker()
{
}

TiUIPicker* TiUIPicker::createPicker(NativeObjectFactory* nativeObjectFactory)
{
    TiUIPicker* obj = new TiUIPicker(nativeObjectFactory);
    obj->initializeTiObject(NULL);
    return obj;
}

void TiUIPicker::initializeTiObject(TiObject* parentContext)
{
    if (!isInitialized())
    {
        TiUIBase::initializeTiObject(parentContext);
        //currently cascades only supports date/time picker that is why we should create native DateTimePicker object here
        NativeObject* obj = getNativeObjectFactory()->createNativeObject(N_TYPE_DATE_TIME_PICKER);
        setNativeObject(obj);
        obj->release();
    }
}

void TiUIPicker::onCreateStaticMembers()
{
    TiUIBase::onCreateStaticMembers();
}
<commit_msg>TIMOB-9876: BlackBerry: Fix build failure Reviewers: JP, David L<commit_after>/**
 * Appcelerator Titanium Mobile
 * Copyright (c) 2009-2012 by Appcelerator, Inc. All Rights Reserved.
 * Licensed under the terms of the Apache Public License
 * Please see the LICENSE included with this distribution for details.
 */

#include "TiUIPicker.h"
#include "TiGenericFunctionObject.h"

TiUIPicker::TiUIPicker(NativeObjectFactory* nativeObjectFactory)
    : TiUIBase("")
{
}

TiUIPicker::~TiUIPicker()
{
}

TiUIPicker* TiUIPicker::createPicker(NativeObjectFactory* nativeObjectFactory)
{
    TiUIPicker* obj = new TiUIPicker(nativeObjectFactory);
    obj->initializeTiObject(NULL);
    return obj;
}

void TiUIPicker::initializeTiObject(TiObject* parentContext)
{
    if (!isInitialized())
    {
        TiUIBase::initializeTiObject(parentContext);
        //currently cascades only supports date/time picker that is why we should create native DateTimePicker object here
        NativeObject* obj = getNativeObjectFactory()->createNativeObject(N_TYPE_DATE_TIME_PICKER);
        setNativeObject(obj);
        obj->release();
    }
}

void TiUIPicker::onCreateStaticMembers()
{
    TiUIBase::onCreateStaticMembers();
}
<|endoftext|>


<commit_before>#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include "camera.hpp"

#pragma comment(lib,"opencv_world320.lib")

static const int N = 256;//文字列の長さ
static const int AOV = 62.2;//ANGLE OF VIEW
//明度について
static const int MAX_VALUE = 255;//明るさ最大
static const int NO_VALUE = 0;//明るさ最小

//時間を元にStringを作る
char* makeTimeString(void)
{
	static char timeString[N];
	time_t timer;//時刻を受け取る変数
	struct tm *timeptr;//日時を集めた構造体ポインタ
	time(&timer);//現在時刻の取得
	timeptr = localtime(&timer);//ポインタ
	strftime(timeString, N, "%Y%m%d-%H%M%S", timeptr);//日時を文字列に変換してｓに代入
	return timeString;
}

char* makeBinaryString(char *timeString)
{
	static char binaryString[N];
	sprintf(binaryString, "%s%s",timeString,"Binary");
	return binaryString;
}

//full_pathを作る
char* makePath(char* name)
{
	static char full_path[N];//NOTE 自動変数をreturn するために使った. smartなやり方か?
	char directry_path[] = "/home/pi/Pictures/";//pathの先頭
	char file_extention[] = ".jpg";//拡張子
	sprintf(full_path, "%s%s%s",directry_path,name,file_extention);
	return full_path;
}
//写真をとる
int takePhoto(char* name)
{
	char full_command[N];
	char front_command[] = "raspistill -o ";//command
	sprintf(full_command, "%s%s", front_command,name);//コマンドの文字列をつなげる。
	system(full_command);//raspistillで静止画を撮って日時を含むファイル名で保存。
	printf("%s\n",full_command);
	//NOTE system関数以外を使うべきか?
	return 0;
}

//二値化画像を作成
cv::Mat binarize(cv::Mat src)
{
	cv::Mat hsv;
	cv::Mat hsv_filtered15 ;//画像の初期化
	cv::Mat hsv_filtered180;//画像の初期化
	cv::cvtColor(src, hsv, CV_BGR2HSV);//入力画像(src)をhsv色空間(dst)に変換
	//inRange(入力画像,下界画像,上界画像,出力画像)
	//「HSV」は、色を色相(Hue)・彩度(Saturation)・明度(Value)
	cv::inRange(hsv, cv::Scalar(0, 45, 70), cv::Scalar(12, 255, MAX_VALUE), hsv_filtered15);
	cv::inRange(hsv, cv::Scalar(160, 45, 70), cv::Scalar(180, 255, MAX_VALUE), hsv_filtered180);
	cv::add(hsv_filtered15,hsv_filtered180,hsv);
	return hsv;
}
//ノイズ除去
cv::Mat rmNoize(cv::Mat src)
{
	cv::erode(src,src,cv::Mat(),cv::Point(-1, -1),10);//縮小処理
	cv::dilate(src,src,cv::Mat(),cv::Point(-1, -1),25);//膨張処理
	cv::erode(src,src,cv::Mat(),cv::Point(-1, -1),15);//縮小処理
	return src;
}

int saveBinary(cv::Mat src,char* path)
{
	cv::Mat binary_img;
	cv::resize(src,binary_img,cv::Size(),0.25,0.25);
	return 0;
}

//写真を撮り画像処理する
cv::Mat Mred(void)
{
	char* stime = makeTimeString();
	printf("%s\n",stime);
	char* sbtime = makeBinaryString(stime);
	printf("%s\n",sbtime);
	char* path = makePath(stime);
	printf("%s\n",path);
	takePhoto(path);
	char* bpath = makePath(sbtime);
	printf("%s\n",path);
 	cv::Mat src = cv::imread(path);//画像の読み込み
	cv::Mat hsv;
	hsv = rmNoize(binarize(src));
	saveBinary(hsv,bpath);
	return hsv;
}

//二値化した画像から1の面積を抽出
double countArea(cv::Mat src)
{

	double Area = src.rows*src.cols;//全ピクセル数
	double redCount = 0; //赤色を認識したピクセルの数
	redCount = cv::countNonZero(src);//赤色部分の面積を計算
	double percentage = 0; //割合
	percentage = (redCount / Area)*100;//割合を計算
	printf("面積のPercentageは%f\n", percentage);
	return percentage;
}

//二値化画像のcenterを角度で返す
double getCenter(cv::Mat src)
{
	cv::Moments mu = cv::moments(src, false);//重心の計算結果をmuに代入
	double mc = mu.m10 / mu.m00;//重心のx座標
	double center = (mc - src.cols / 2) * AOV / src.cols;//正規化
	printf("重心の位置は%f\n",center);
	return center;
}
<commit_msg>dbeug<commit_after>#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include "camera.hpp"

#pragma comment(lib,"opencv_world320.lib")

static const int N = 256;//文字列の長さ
static const int AOV = 62.2;//ANGLE OF VIEW
//明度について
static const int MAX_VALUE = 255;//明るさ最大
static const int NO_VALUE = 0;//明るさ最小

//時間を元にStringを作る
char* makeTimeString(void)
{
	static char timeString[N];
	time_t timer;//時刻を受け取る変数
	struct tm *timeptr;//日時を集めた構造体ポインタ
	time(&timer);//現在時刻の取得
	timeptr = localtime(&timer);//ポインタ
	strftime(timeString, N, "%Y%m%d-%H%M%S", timeptr);//日時を文字列に変換してｓに代入
	return timeString;
}

char* makeBinaryString(char *timeString)
{
	static char binaryString[N];
	sprintf(binaryString, "%s%s",timeString,"Binary");
	return binaryString;
}

//full_pathを作る
char* makePath(char* name)
{
	static char full_path[N];//NOTE 自動変数をreturn するために使った. smartなやり方か?
	char directry_path[] = "/home/pi/Pictures/";//pathの先頭
	char file_extention[] = ".jpg";//拡張子
	sprintf(full_path, "%s%s%s",directry_path,name,file_extention);
	return full_path;
}
//写真をとる
int takePhoto(char* name)
{
	char full_command[N];
	char front_command[] = "raspistill -o ";//command
	sprintf(full_command, "%s%s", front_command,name);//コマンドの文字列をつなげる。
	system(full_command);//raspistillで静止画を撮って日時を含むファイル名で保存。
	printf("%s\n",full_command);
	//NOTE system関数以外を使うべきか?
	return 0;
}

//二値化画像を作成
cv::Mat binarize(cv::Mat src)
{
	cv::Mat hsv;
	cv::Mat hsv_filtered15 ;//画像の初期化
	cv::Mat hsv_filtered180;//画像の初期化
	cv::cvtColor(src, hsv, CV_BGR2HSV);//入力画像(src)をhsv色空間(dst)に変換
	//inRange(入力画像,下界画像,上界画像,出力画像)
	//「HSV」は、色を色相(Hue)・彩度(Saturation)・明度(Value)
	cv::inRange(hsv, cv::Scalar(0, 45, 70), cv::Scalar(12, 255, MAX_VALUE), hsv_filtered15);
	cv::inRange(hsv, cv::Scalar(160, 45, 70), cv::Scalar(180, 255, MAX_VALUE), hsv_filtered180);
	cv::add(hsv_filtered15,hsv_filtered180,hsv);
	return hsv;
}
//ノイズ除去
cv::Mat rmNoize(cv::Mat src)
{
	cv::erode(src,src,cv::Mat(),cv::Point(-1, -1),10);//縮小処理
	cv::dilate(src,src,cv::Mat(),cv::Point(-1, -1),25);//膨張処理
	cv::erode(src,src,cv::Mat(),cv::Point(-1, -1),15);//縮小処理
	return src;
}

int saveBinary(cv::Mat src,char* path)
{
	cv::Mat binary_img;
	cv::resize(src,binary_img,cv::Size(),0.25,0.25);
	return 0;
}

//写真を撮り画像処理する
cv::Mat Mred(void)
{
	char* stime = makeTimeString();
	printf("%s\n",stime);
	char* sbtime = makeBinaryString(stime);
	printf("%s\n",sbtime);
	const char* path = makePath(stime);
	printf("%s\n",path);
	takePhoto(path);
	char* bpath = makePath(sbtime);
	printf("%s\n",path);
 	cv::Mat src = cv::imread(path);//画像の読み込み
	cv::Mat hsv;
	hsv = rmNoize(binarize(src));
	saveBinary(hsv,bpath);
	return hsv;
}

//二値化した画像から1の面積を抽出
double countArea(cv::Mat src)
{

	double Area = src.rows*src.cols;//全ピクセル数
	double redCount = 0; //赤色を認識したピクセルの数
	redCount = cv::countNonZero(src);//赤色部分の面積を計算
	double percentage = 0; //割合
	percentage = (redCount / Area)*100;//割合を計算
	printf("面積のPercentageは%f\n", percentage);
	return percentage;
}

//二値化画像のcenterを角度で返す
double getCenter(cv::Mat src)
{
	cv::Moments mu = cv::moments(src, false);//重心の計算結果をmuに代入
	double mc = mu.m10 / mu.m00;//重心のx座標
	double center = (mc - src.cols / 2) * AOV / src.cols;//正規化
	printf("重心の位置は%f\n",center);
	return center;
}
<|endoftext|>