<commit_before>// Copyright (c) 2013, German Neuroinformatics Node (G-Node)
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted under the terms of the BSD License. See
// LICENSE file in the root of the Project.

#include "H5DataType.hpp"

#include <stdexcept>
#include <iostream>
#include <cassert>
#include <string>
#include <memory>
#include <cstdlib>

namespace nix {
namespace hdf5 {
namespace h5x {

DataType DataType::copy(hid_t source) {
    DataType hi_copy = H5Tcopy(source);
    hi_copy.check("Could not copy type");
    return hi_copy;
}

DataType DataType::make(H5T_class_t klass, size_t size) {
    DataType dt = H5Tcreate(klass, size);
    dt.check("Could not create datatype");
    return dt;
}

DataType DataType::makeStrType(size_t size) {
    DataType str_type = H5Tcopy(H5T_C_S1);
    str_type.check("Could not create string type");
    str_type.size(size);
    return str_type;
}

DataType DataType::makeCompound(size_t size) {
    DataType res = H5Tcreate(H5T_COMPOUND, size);
    res.check("Could not create compound type");
    return res;
}

DataType DataType::makeEnum(const DataType &base) {
    DataType res = H5Tenum_create(base.h5id());
    res.check("Could not create enum type");
    return res;
}

H5T_class_t DataType::class_t() const {
    return H5Tget_class(hid);
}

void DataType::size(size_t t) {
    HErr res = H5Tset_size(hid, t);
    res.check("DataType::size: Could not set size");
}

size_t DataType::size() const {
    return H5Tget_size(hid); //FIXME: throw on 0?
}

void DataType::sign(H5T_sign_t sign) {
    HErr res = H5Tset_sign(hid, sign);
    res.check("DataType::sign(): H5Tset_sign failed");
}

H5T_sign_t DataType::sign() const {
    H5T_sign_t res = H5Tget_sign(hid);
    return res;
}

bool DataType::isVariableString() const {
    HTri res = H5Tis_variable_str(hid);
    res.check("DataType::isVariableString(): H5Tis_variable_str failed");
    return res.result();
}

bool DataType::isCompound() const {
    return class_t() == H5T_COMPOUND;
}

unsigned int DataType::member_count() const {
    int res = H5Tget_nmembers(hid);
    if (res < 0) {
        throw H5Exception("DataType::member_count(): H5Tget_nmembers faild");
    }
    return static_cast<unsigned  int>(res);
}

H5T_class_t DataType::member_class(unsigned int index) const {
    return H5Tget_member_class(hid, index);
}

std::string DataType::member_name(unsigned int index) const {
    char *data = H5Tget_member_name(hid, index);
    std::string res(data);
    std::free(data);
    return res;
}

std::vector<std::string> DataType::member_names() const {
    unsigned int c = member_count();
    std::vector<std::string> names;

    for (unsigned int i = 0; i < c; i++) {
        names.emplace_back(member_name(i));
    }

    return names;
}

size_t DataType::member_offset(unsigned int index) const {
    return H5Tget_member_offset(hid, index);
}

DataType DataType::member_type(unsigned int index) const {
    h5x::DataType res = H5Tget_member_type(hid, index);
    res.check("DataType::member_type(): H5Tget_member_type failed");
    return res;
}

void DataType::insert(const std::string &name, size_t offset, const DataType &dtype) {
    HErr res = H5Tinsert(hid, name.c_str(), offset, dtype.hid);
    res.check("DataType::insert(): H5Tinsert failed.");
}

void DataType::insert(const std::string &name, void *value) {
    HErr res = H5Tenum_insert(hid, name.c_str(), value);
    res.check("DataType::insert(): H5Tenum_insert failed.");
}

void DataType::enum_valueof(const std::string &name, void *value) {
    HErr res = H5Tenum_valueof(hid, name.c_str(), value);
    res.check("DataType::enum_valueof(): H5Tenum_valueof failed");
}

bool DataType::enum_equal(const DataType &other) {
    if (class_t() != H5T_ENUM || other.class_t() != H5T_ENUM) {
        return false;
    }

    std::vector<std::string> a_names = this->member_names();
    std::vector<std::string> b_names = other.member_names();

    if (a_names.size() != b_names.size()) {
        return false;
    }

    std::sort(std::begin(a_names), std::end(a_names));
    std::sort(std::begin(b_names), std::end(b_names));

    return std::equal(std::begin(a_names),
                      std::end(a_names),
                      std::begin(b_names));
}

} // h5x

h5x::DataType data_type_to_h5_filetype(DataType dtype) {

   /* The switch is structred in a way in order to get
      warnings from the compiler when not all cases are
      handled and throw an exception if one of the not
      handled cases actually appears (i.e., we have no
      default case, because that silences the compiler.)
   */

    switch (dtype) {

        case DataType::Bool:   return h5x::DataType::copy(H5T_STD_B8LE);
        case DataType::Int8:   return h5x::DataType::copy(H5T_STD_I8LE);
        case DataType::Int16:  return h5x::DataType::copy(H5T_STD_I16LE);
        case DataType::Int32:  return h5x::DataType::copy(H5T_STD_I32LE);
        case DataType::Int64:  return h5x::DataType::copy(H5T_STD_I64LE);
        case DataType::UInt8:  return h5x::DataType::copy(H5T_STD_U8LE);
        case DataType::UInt16: return h5x::DataType::copy(H5T_STD_U16LE);
        case DataType::UInt32: return h5x::DataType::copy(H5T_STD_U32LE);
        case DataType::UInt64: return h5x::DataType::copy(H5T_STD_U64LE);
        case DataType::Float:  return h5x::DataType::copy(H5T_IEEE_F32LE);
        case DataType::Double: return h5x::DataType::copy(H5T_IEEE_F64LE);
        case DataType::String: return h5x::DataType::makeStrType();
        //shall we create our own OPAQUE type?
        case DataType::Opaque: return h5x::DataType::copy(H5T_NATIVE_OPAQUE);

        case DataType::Char: break; //FIXME
        case DataType::Nothing: break;
    }

    throw std::invalid_argument("Unkown DataType"); //FIXME
}

h5x::DataType data_type_to_h5_memtype(DataType dtype) {

    // See data_type_to_h5_filetype for the reason why the switch is structured
    // in the way it is.

    switch(dtype) {
        //special case the bool
        //we treat them as bit fields for now, since hdf5 has no bool support
        //as of 1.8.12
        case DataType::Bool:   return h5x::DataType::copy(H5T_NATIVE_B8);
        case DataType::Int8:   return h5x::DataType::copy(H5T_NATIVE_INT8);
        case DataType::Int16:  return h5x::DataType::copy(H5T_NATIVE_INT16);
        case DataType::Int32:  return h5x::DataType::copy(H5T_NATIVE_INT32);
        case DataType::Int64:  return h5x::DataType::copy(H5T_NATIVE_INT64);
        case DataType::UInt8:  return h5x::DataType::copy(H5T_NATIVE_UINT8);
        case DataType::UInt16: return h5x::DataType::copy(H5T_NATIVE_UINT16);
        case DataType::UInt32: return h5x::DataType::copy(H5T_NATIVE_UINT32);
        case DataType::UInt64: return h5x::DataType::copy(H5T_NATIVE_UINT64);
        case DataType::Float:  return h5x::DataType::copy(H5T_NATIVE_FLOAT);
        case DataType::Double: return h5x::DataType::copy(H5T_NATIVE_DOUBLE);
        case DataType::String: return h5x::DataType::makeStrType();
        case DataType::Opaque: return h5x::DataType::copy(H5T_NATIVE_OPAQUE);

        case DataType::Char: break; //FIXME
        case DataType::Nothing: break;
    }

    throw std::invalid_argument("DataType not handled!"); //FIXME
}

h5x::DataType data_type_to_h5(DataType dtype, bool for_memory) {
    if (for_memory) {
        return data_type_to_h5_memtype(dtype);
    } else {
        return data_type_to_h5_filetype(dtype);
    }
}

#define NOT_IMPLEMENTED false

DataType
data_type_from_h5(H5T_class_t vclass, size_t vsize, H5T_sign_t vsign)
{
    if (vclass == H5T_INTEGER) {
        switch (vsize) {
        case 1: return vsign == H5T_SGN_2 ? DataType::Int8  : DataType::UInt8;
        case 2: return vsign == H5T_SGN_2 ? DataType::Int16 : DataType::UInt16;
        case 4: return vsign == H5T_SGN_2 ? DataType::Int32 : DataType::UInt32;
        case 8: return vsign == H5T_SGN_2 ? DataType::Int64 : DataType::UInt64;
        }
    } else if (vclass == H5T_FLOAT) {
        return vsize == 8 ? DataType::Double : DataType::Float;
    } else if (vclass == H5T_STRING) {
        return DataType::String;
    } else if (vclass == H5T_BITFIELD) {
        switch (vsize) {
        case 1: return DataType::Bool;
        }
    }

    std::cerr << "FIXME: Not implemented " << vclass << " " << vsize << " " << vsign << " " << std::endl;
    assert(NOT_IMPLEMENTED);
    return DataType::Nothing;
}

DataType data_type_from_h5(const h5x::DataType &dtype) {

    H5T_class_t ftclass = dtype.class_t();

    size_t     size;
    H5T_sign_t sign;

    if (ftclass == H5T_COMPOUND) {
        //if it is a compound data type then it must be a
        //a property dataset, we can handle that
        int nmems = dtype.member_count();
        assert(nmems == 6);
        h5x::DataType vtype = dtype.member_type(0);

        ftclass = vtype.class_t();
        size = vtype.size();
        sign = vtype.sign();

    } else if (ftclass == H5T_OPAQUE) {
        return DataType::Opaque;
    } else {
        size = dtype.size();
        sign = dtype.sign();
    }

    return data_type_from_h5(ftclass, size, sign);
}

} // namespace hdf5
} // namespace nix
<commit_msg>[h5x] New boolean enum representations<commit_after>// Copyright (c) 2013, German Neuroinformatics Node (G-Node)
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted under the terms of the BSD License. See
// LICENSE file in the root of the Project.

#include "H5DataType.hpp"

#include <stdexcept>
#include <iostream>
#include <cassert>
#include <string>
#include <memory>
#include <cstdlib>

namespace nix {
namespace hdf5 {
namespace h5x {

DataType DataType::copy(hid_t source) {
    DataType hi_copy = H5Tcopy(source);
    hi_copy.check("Could not copy type");
    return hi_copy;
}

DataType DataType::make(H5T_class_t klass, size_t size) {
    DataType dt = H5Tcreate(klass, size);
    dt.check("Could not create datatype");
    return dt;
}

DataType DataType::makeStrType(size_t size) {
    DataType str_type = H5Tcopy(H5T_C_S1);
    str_type.check("Could not create string type");
    str_type.size(size);
    return str_type;
}

DataType DataType::makeCompound(size_t size) {
    DataType res = H5Tcreate(H5T_COMPOUND, size);
    res.check("Could not create compound type");
    return res;
}

DataType DataType::makeEnum(const DataType &base) {
    DataType res = H5Tenum_create(base.h5id());
    res.check("Could not create enum type");
    return res;
}

H5T_class_t DataType::class_t() const {
    return H5Tget_class(hid);
}

void DataType::size(size_t t) {
    HErr res = H5Tset_size(hid, t);
    res.check("DataType::size: Could not set size");
}

size_t DataType::size() const {
    return H5Tget_size(hid); //FIXME: throw on 0?
}

void DataType::sign(H5T_sign_t sign) {
    HErr res = H5Tset_sign(hid, sign);
    res.check("DataType::sign(): H5Tset_sign failed");
}

H5T_sign_t DataType::sign() const {
    H5T_sign_t res = H5Tget_sign(hid);
    return res;
}

bool DataType::isVariableString() const {
    HTri res = H5Tis_variable_str(hid);
    res.check("DataType::isVariableString(): H5Tis_variable_str failed");
    return res.result();
}

bool DataType::isCompound() const {
    return class_t() == H5T_COMPOUND;
}

unsigned int DataType::member_count() const {
    int res = H5Tget_nmembers(hid);
    if (res < 0) {
        throw H5Exception("DataType::member_count(): H5Tget_nmembers faild");
    }
    return static_cast<unsigned  int>(res);
}

H5T_class_t DataType::member_class(unsigned int index) const {
    return H5Tget_member_class(hid, index);
}

std::string DataType::member_name(unsigned int index) const {
    char *data = H5Tget_member_name(hid, index);
    std::string res(data);
    std::free(data);
    return res;
}

std::vector<std::string> DataType::member_names() const {
    unsigned int c = member_count();
    std::vector<std::string> names;

    for (unsigned int i = 0; i < c; i++) {
        names.emplace_back(member_name(i));
    }

    return names;
}

size_t DataType::member_offset(unsigned int index) const {
    return H5Tget_member_offset(hid, index);
}

DataType DataType::member_type(unsigned int index) const {
    h5x::DataType res = H5Tget_member_type(hid, index);
    res.check("DataType::member_type(): H5Tget_member_type failed");
    return res;
}

void DataType::insert(const std::string &name, size_t offset, const DataType &dtype) {
    HErr res = H5Tinsert(hid, name.c_str(), offset, dtype.hid);
    res.check("DataType::insert(): H5Tinsert failed.");
}

void DataType::insert(const std::string &name, void *value) {
    HErr res = H5Tenum_insert(hid, name.c_str(), value);
    res.check("DataType::insert(): H5Tenum_insert failed.");
}

void DataType::enum_valueof(const std::string &name, void *value) {
    HErr res = H5Tenum_valueof(hid, name.c_str(), value);
    res.check("DataType::enum_valueof(): H5Tenum_valueof failed");
}

bool DataType::enum_equal(const DataType &other) {
    if (class_t() != H5T_ENUM || other.class_t() != H5T_ENUM) {
        return false;
    }

    std::vector<std::string> a_names = this->member_names();
    std::vector<std::string> b_names = other.member_names();

    if (a_names.size() != b_names.size()) {
        return false;
    }

    std::sort(std::begin(a_names), std::end(a_names));
    std::sort(std::begin(b_names), std::end(b_names));

    return std::equal(std::begin(a_names),
                      std::end(a_names),
                      std::begin(b_names));
}

} // h5x

h5x::DataType make_file_booltype() {
    h5x::DataType booltype = h5x::DataType::makeEnum(H5T_NATIVE_INT8);
    booltype.insert("FALSE", 0UL);
    booltype.insert("TRUE", 1UL);
    return booltype;
}

h5x::DataType make_mem_booltype() {
    h5x::DataType booltype = h5x::DataType::make(H5T_ENUM, sizeof(bool));
    booltype.insert("FALSE", false);
    booltype.insert("TRUE", true);
    return booltype;
}

static const h5x::DataType boolfiletype = make_file_booltype();
static const h5x::DataType boolmemtype = make_mem_booltype();

h5x::DataType data_type_to_h5_filetype(DataType dtype) {

   /* The switch is structured in a way in order to get
      warnings from the compiler when not all cases are
      handled and throw an exception if one of the not
      handled cases actually appears (i.e., we have no
      default case, because that silences the compiler.)
   */

    switch (dtype) {

        case DataType::Bool:   return boolfiletype;
        case DataType::Int8:   return h5x::DataType::copy(H5T_STD_I8LE);
        case DataType::Int16:  return h5x::DataType::copy(H5T_STD_I16LE);
        case DataType::Int32:  return h5x::DataType::copy(H5T_STD_I32LE);
        case DataType::Int64:  return h5x::DataType::copy(H5T_STD_I64LE);
        case DataType::UInt8:  return h5x::DataType::copy(H5T_STD_U8LE);
        case DataType::UInt16: return h5x::DataType::copy(H5T_STD_U16LE);
        case DataType::UInt32: return h5x::DataType::copy(H5T_STD_U32LE);
        case DataType::UInt64: return h5x::DataType::copy(H5T_STD_U64LE);
        case DataType::Float:  return h5x::DataType::copy(H5T_IEEE_F32LE);
        case DataType::Double: return h5x::DataType::copy(H5T_IEEE_F64LE);
        case DataType::String: return h5x::DataType::makeStrType();
        //shall we create our own OPAQUE type?
        case DataType::Opaque: return h5x::DataType::copy(H5T_NATIVE_OPAQUE);

        case DataType::Char: break; //FIXME
        case DataType::Nothing: break;
    }

    throw std::invalid_argument("Unkown DataType"); //FIXME
}

h5x::DataType data_type_to_h5_memtype(DataType dtype) {

    // See data_type_to_h5_filetype for the reason why the switch is structured
    // in the way it is.

    switch(dtype) {
        case DataType::Bool:   return boolmemtype;
        case DataType::Int8:   return h5x::DataType::copy(H5T_NATIVE_INT8);
        case DataType::Int16:  return h5x::DataType::copy(H5T_NATIVE_INT16);
        case DataType::Int32:  return h5x::DataType::copy(H5T_NATIVE_INT32);
        case DataType::Int64:  return h5x::DataType::copy(H5T_NATIVE_INT64);
        case DataType::UInt8:  return h5x::DataType::copy(H5T_NATIVE_UINT8);
        case DataType::UInt16: return h5x::DataType::copy(H5T_NATIVE_UINT16);
        case DataType::UInt32: return h5x::DataType::copy(H5T_NATIVE_UINT32);
        case DataType::UInt64: return h5x::DataType::copy(H5T_NATIVE_UINT64);
        case DataType::Float:  return h5x::DataType::copy(H5T_NATIVE_FLOAT);
        case DataType::Double: return h5x::DataType::copy(H5T_NATIVE_DOUBLE);
        case DataType::String: return h5x::DataType::makeStrType();
        case DataType::Opaque: return h5x::DataType::copy(H5T_NATIVE_OPAQUE);

        case DataType::Char: break; //FIXME
        case DataType::Nothing: break;
    }

    throw std::invalid_argument("DataType not handled!"); //FIXME
}

h5x::DataType data_type_to_h5(DataType dtype, bool for_memory) {
    if (for_memory) {
        return data_type_to_h5_memtype(dtype);
    } else {
        return data_type_to_h5_filetype(dtype);
    }
}

#define NOT_IMPLEMENTED false

DataType
data_type_from_h5(H5T_class_t vclass, size_t vsize, H5T_sign_t vsign)
{
    if (vclass == H5T_INTEGER) {
        switch (vsize) {
        case 1: return vsign == H5T_SGN_2 ? DataType::Int8  : DataType::UInt8;
        case 2: return vsign == H5T_SGN_2 ? DataType::Int16 : DataType::UInt16;
        case 4: return vsign == H5T_SGN_2 ? DataType::Int32 : DataType::UInt32;
        case 8: return vsign == H5T_SGN_2 ? DataType::Int64 : DataType::UInt64;
        }
    } else if (vclass == H5T_FLOAT) {
        return vsize == 8 ? DataType::Double : DataType::Float;
    } else if (vclass == H5T_STRING) {
        return DataType::String;
    } else if (vclass == H5T_BITFIELD) {
        switch (vsize) {
        case 1: return DataType::Bool;
        }
    }

    std::cerr << "FIXME: Not implemented " << vclass << " " << vsize << " " << vsign << " " << std::endl;
    assert(NOT_IMPLEMENTED);
    return DataType::Nothing;
}

DataType data_type_from_h5(const h5x::DataType &dtype) {

    H5T_class_t ftclass = dtype.class_t();

    size_t     size;
    H5T_sign_t sign;

    if (ftclass == H5T_COMPOUND) {
        //if it is a compound data type then it must be a
        //a property dataset, we can handle that
        int nmems = dtype.member_count();
        assert(nmems == 6);
        h5x::DataType vtype = dtype.member_type(0);

        ftclass = vtype.class_t();
        size = vtype.size();
        sign = vtype.sign();

    } else if (ftclass == H5T_OPAQUE) {
        return DataType::Opaque;
    } else {
        size = dtype.size();
        sign = dtype.sign();
    }

    return data_type_from_h5(ftclass, size, sign);
}

} // namespace hdf5
} // namespace nix
<|endoftext|>


<commit_before><commit_msg>This header doesn't need to include queryparam.hxx.<commit_after><|endoftext|>


<commit_before>/******************************************
 author      : Zhizhong Pan
 E-mail      : zhizhop@g.clemson.edu
 *******************************************/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>

//import OpenCL header
#ifdef __APPLE__
#include <OpenCL/opencl.h>
#include <OpenCL/cl.h>
#else
#include <CL/cl.h>
#endif

#include "RGU.h"

#define LWS 256

//Globl Variables declare
static unsigned int GWS;
static double* vector1;       // The first input vector
static double* vector2;       // The secaond input vector

// OpenCL globals
cl_platform_id platform;
cl_context context;
cl_device_id *device;
cl_command_queue command;
cl_kernel multiKernel, reduceKernel;
cl_program program;
cl_mem inputVector1, inputVector2, output[2];

void
initCL()
{
    int err;
    size_t contxtSize, kernelSize;
    char *kernelSource;
    unsigned int gpuDevCount;

    err = RGUGetPlatformID(&platform);
    err = clGetDeviceIDs(platform, CL_DEVICE_TYPE_GPU, 0, NULL, &gpuDevCount);
    device = new cl_device_id[gpuDevCount];
    err = clGetDeviceIDs(platform, CL_DEVICE_TYPE_GPU, gpuDevCount, device, NULL);

    cl_context_properties props[] = {CL_CONTEXT_PLATFORM, (cl_context_properties)platform, 0};
    context = clCreateContext(props, 1, &device[0], NULL, NULL, &err);
    command = clCreateCommandQueue(context,device[0],0,&err);

    kernelSource = RGULoadProgSource("kernel.cl","", &kernelSize);
    program = clCreateProgramWithSource(context,1, (const char **)&kernelSource, NULL, NULL);
    clBuildProgram(program,0,NULL,NULL,NULL,NULL);
    multiKernel = clCreateKernel(program,"multi",NULL);
    reduceKernel = clCreateKernel(program, "reduce", NULL);

}

void
setBuffers()
{
    inputVector1 = clCreateBuffer(context,CL_MEM_READ_ONLY|CL_MEM_COPY_HOST_PTR,
                                GWS * sizeof(double),vector1,NULL);
    inputVector2 = clCreateBuffer(context,CL_MEM_READ_ONLY|CL_MEM_COPY_HOST_PTR,
                                GWS * sizeof(double),vector2,NULL);

    output[0] = clCreateBuffer(context,CL_MEM_READ_WRITE, (GWS) * sizeof(double),NULL,NULL);
    output[1] = clCreateBuffer(context,CL_MEM_READ_WRITE, (GWS) * sizeof(double),NULL,NULL);
}

static double*
readFile(char* filename){
    unsigned int length;
    double* vector;
    FILE *filePtr;

    filePtr = fopen(filename, "r");
    if (filePtr != NULL){
        fread(&length, sizeof(unsigned int), 1, filePtr);
        // make the init vector size be an integer multiple of LWS
        if (length % LWS != 0)
            GWS = LWS - length % LWS + length;
        vector = new double[GWS];
        fread(vector, sizeof(double), length , filePtr);

        // make sure the padding elements are zero
        for (int i  = length; i < GWS; i++)
            vector[i] = 0.0;
    }else{
        fprintf(stderr, "Can't open file %s \n", filename);
        exit(-1);
    }
    fclose(filePtr);
    return vector;
}

static double
dotProd(double* vector1, double* vector2)
{
    initCL();
    setBuffers();

    unsigned int from = 0, to = 1;
    unsigned int modVal;
    double result[1];
    double result2[GWS];
    size_t workItemCount[1] = {GWS};    // store global work size
    size_t localItemCout[1] = {LWS};

    clSetKernelArg(multiKernel,0,sizeof(cl_mem),(void *)&inputVector1);
    clSetKernelArg(multiKernel,1,sizeof(cl_mem),(void *)&inputVector2);
    clSetKernelArg(multiKernel,2,sizeof(cl_mem),(void *)output[0]);

    clEnqueueNDRangeKernel(command, multiKernel,1,NULL,workItemCount,localItemCout,0,NULL,NULL);

    while (workItemCount[0]  > 1) {

        modVal = workItemCount[0] % localItemCout[0];
       if (modVal != 0)
            workItemCount[0] += localItemCout[0] - modVal;

        clSetKernelArg(reduceKernel,0,sizeof(cl_mem),(void *)output[from]);
        clSetKernelArg(reduceKernel,1,sizeof(cl_mem),(void *)output[to]);

        // do ping-pong
        from = 1 - from;
        to = 1 -to;

        printf("=================================  before ======================================");
        printf("--------------------------------------- from ---------------------------------\n");
        clEnqueueReadBuffer(command,output[from],CL_TRUE,0,workItemCount[0]*sizeof(double),result2,0,NULL,NULL);
        for (int i = 0; i < workItemCount[0]; i++)
            printf("%f, ", result2[i]);
        printf("--------------------------------------- to ---------------------------------\n");
        clEnqueueReadBuffer(command, output[to],CL_TRUE,0,workItemCount[0]*sizeof(double),result2,0,NULL,NULL);
        for (int i = 0; i < workItemCount[0]; i++)
            printf("%f, ", result2[i]);

        clEnqueueNDRangeKernel(command,reduceKernel,1,NULL, workItemCount ,localItemCout,0,NULL,NULL);

        printf("=================================  after ======================================");
        clEnqueueReadBuffer(command,output[from],CL_TRUE,0,workItemCount[0]*sizeof(double),result2,0,NULL,NULL);
        for (int i = 0; i < workItemCount[0]; i++)
            printf("%f, ", result2[i]);
        printf("--------------------------------------- to ---------------------------------\n");
        clEnqueueReadBuffer(command, output[to],CL_TRUE,0,workItemCount[0]*sizeof(double),result2,0,NULL,NULL);
        for (int i = 0; i < workItemCount[0]; i++)
            printf("%f, ", result2[i]);

        workItemCount[0] = ceil( workItemCount[0]  / double (localItemCout[0]));
    }

    clEnqueueReadBuffer(command,output[from],CL_TRUE,0,1*sizeof(double),result,0,NULL,NULL);

    return result[0];

}

void
cleanup(int signo)
{
    int i;

    // clean device
    clReleaseProgram(program);
    clReleaseContext(context);
    clReleaseKernel(multiKernel);
    clReleaseKernel(reduceKernel);
    clReleaseCommandQueue(command);
    clReleaseMemObject(inputVector1);
    clReleaseMemObject(inputVector2);
    clReleaseMemObject(output[0]);
    clReleaseMemObject(output[1]);
    exit(0);
}

int
main(int argc, char * argv[])
{
    if (argc < 3) {
        fprintf(stderr, "Error! Usage: ./bigdot file file \n");
        exit(-1);
    }

    signal(SIGUSR1, cleanup);
    vector1 = readFile(argv[1]);
    vector2 = readFile(argv[2]);
    double result = dotProd(vector1, vector2);
    for (int i = 0; i < GWS; i++){
//	printf("%f ,", vector1[i]);
    }

    printf("Result: %f\n", result);
    cleanup(SIGUSR1);
    return 0;
}
<commit_msg>add test suit 2<commit_after>/******************************************
 author      : Zhizhong Pan
 E-mail      : zhizhop@g.clemson.edu
 *******************************************/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>

//import OpenCL header
#ifdef __APPLE__
#include <OpenCL/opencl.h>
#include <OpenCL/cl.h>
#else
#include <CL/cl.h>
#endif

#include "RGU.h"

#define LWS 256

//Globl Variables declare
static unsigned int GWS;
static double* vector1;       // The first input vector
static double* vector2;       // The secaond input vector

// OpenCL globals
cl_platform_id platform;
cl_context context;
cl_device_id *device;
cl_command_queue command;
cl_kernel multiKernel, reduceKernel;
cl_program program;
cl_mem inputVector1, inputVector2, output[2];

void
initCL()
{
    int err;
    size_t contxtSize, kernelSize;
    char *kernelSource;
    unsigned int gpuDevCount;

    err = RGUGetPlatformID(&platform);
    err = clGetDeviceIDs(platform, CL_DEVICE_TYPE_GPU, 0, NULL, &gpuDevCount);
    device = new cl_device_id[gpuDevCount];
    err = clGetDeviceIDs(platform, CL_DEVICE_TYPE_GPU, gpuDevCount, device, NULL);

    cl_context_properties props[] = {CL_CONTEXT_PLATFORM, (cl_context_properties)platform, 0};
    context = clCreateContext(props, 1, &device[0], NULL, NULL, &err);
    command = clCreateCommandQueue(context,device[0],0,&err);

    kernelSource = RGULoadProgSource("kernel.cl","", &kernelSize);
    program = clCreateProgramWithSource(context,1, (const char **)&kernelSource, NULL, NULL);
    clBuildProgram(program,0,NULL,NULL,NULL,NULL);
    multiKernel = clCreateKernel(program,"multi",NULL);
    reduceKernel = clCreateKernel(program, "reduce", NULL);

}

void
setBuffers()
{
    inputVector1 = clCreateBuffer(context,CL_MEM_READ_ONLY|CL_MEM_COPY_HOST_PTR,
                                GWS * sizeof(double),vector1,NULL);
    inputVector2 = clCreateBuffer(context,CL_MEM_READ_ONLY|CL_MEM_COPY_HOST_PTR,
                                GWS * sizeof(double),vector2,NULL);

    output[0] = clCreateBuffer(context,CL_MEM_READ_WRITE, (GWS) * sizeof(double),NULL,NULL);
    output[1] = clCreateBuffer(context,CL_MEM_READ_WRITE, (GWS) * sizeof(double),NULL,NULL);
}

static double*
readFile(char* filename){
    unsigned int length;
    double* vector;
    FILE *filePtr;

    filePtr = fopen(filename, "r");
    if (filePtr != NULL){
        fread(&length, sizeof(unsigned int), 1, filePtr);
        // make the init vector size be an integer multiple of LWS
        if (length % LWS != 0)
            GWS = LWS - length % LWS + length;
        vector = new double[GWS];
        fread(vector, sizeof(double), length , filePtr);

        // make sure the padding elements are zero
        for (int i  = length; i < GWS; i++)
            vector[i] = 0.0;
    }else{
        fprintf(stderr, "Can't open file %s \n", filename);
        exit(-1);
    }
    fclose(filePtr);
    return vector;
}

static double
dotProd(double* vector1, double* vector2)
{
    initCL();
    setBuffers();

    unsigned int from = 0, to = 1;
    unsigned int modVal;
    double result[1];
    double result2[GWS];
    size_t workItemCount[1] = {GWS};    // store global work size
    size_t localItemCout[1] = {LWS};

    clSetKernelArg(multiKernel,0,sizeof(cl_mem),(void *)&inputVector1);
    clSetKernelArg(multiKernel,1,sizeof(cl_mem),(void *)&inputVector2);
    clSetKernelArg(multiKernel,2,sizeof(cl_mem),(void *)output[0]);

    clEnqueueNDRangeKernel(command, multiKernel,1,NULL,workItemCount,localItemCout,0,NULL,NULL);
    printf("--------------------------------------- from ---------------------------------\n");
    clEnqueueReadBuffer(command,output[from],CL_TRUE,0,workItemCount[0]*sizeof(double),result2,0,NULL,NULL);
    for (int i = 0; i < workItemCount[0]; i++)
        printf("%f, ", result2[i]);

    while (workItemCount[0]  > 1) {

        modVal = workItemCount[0] % localItemCout[0];
       if (modVal != 0)
            workItemCount[0] += localItemCout[0] - modVal;

        clSetKernelArg(reduceKernel,0,sizeof(cl_mem),(void *)output[from]);
        clSetKernelArg(reduceKernel,1,sizeof(cl_mem),(void *)output[to]);

        // do ping-pong
        from = 1 - from;
        to = 1 -to;

        printf("=================================  before ======================================\n");
        printf("--------------------------------------- from ---------------------------------\n");
        clEnqueueReadBuffer(command,output[from],CL_TRUE,0,workItemCount[0]*sizeof(double),result2,0,NULL,NULL);
        for (int i = 0; i < workItemCount[0]; i++)
            printf("%f, ", result2[i]);
        printf("--------------------------------------- to ---------------------------------\n");
        clEnqueueReadBuffer(command, output[to],CL_TRUE,0,workItemCount[0]*sizeof(double),result2,0,NULL,NULL);
        for (int i = 0; i < workItemCount[0]; i++)
            printf("%f, ", result2[i]);

        clEnqueueNDRangeKernel(command,reduceKernel,1,NULL, workItemCount ,localItemCout,0,NULL,NULL);

        printf("=================================  after ======================================\n");
        clEnqueueReadBuffer(command,output[from],CL_TRUE,0,workItemCount[0]*sizeof(double),result2,0,NULL,NULL);
        for (int i = 0; i < workItemCount[0]; i++)
            printf("%f, ", result2[i]);
        printf("--------------------------------------- to ---------------------------------\n");
        clEnqueueReadBuffer(command, output[to],CL_TRUE,0,workItemCount[0]*sizeof(double),result2,0,NULL,NULL);
        for (int i = 0; i < workItemCount[0]; i++)
            printf("%f, ", result2[i]);

        workItemCount[0] = ceil( workItemCount[0]  / double (localItemCout[0]));
    }

    clEnqueueReadBuffer(command,output[from],CL_TRUE,0,1*sizeof(double),result,0,NULL,NULL);

    return result[0];

}

void
cleanup(int signo)
{
    int i;

    // clean device
    clReleaseProgram(program);
    clReleaseContext(context);
    clReleaseKernel(multiKernel);
    clReleaseKernel(reduceKernel);
    clReleaseCommandQueue(command);
    clReleaseMemObject(inputVector1);
    clReleaseMemObject(inputVector2);
    clReleaseMemObject(output[0]);
    clReleaseMemObject(output[1]);
    exit(0);
}

int
main(int argc, char * argv[])
{
    if (argc < 3) {
        fprintf(stderr, "Error! Usage: ./bigdot file file \n");
        exit(-1);
    }

    //signal(SIGUSR1, cleanup);
    vector1 = readFile(argv[1]);
    vector2 = readFile(argv[2]);
    double result = dotProd(vector1, vector2);
    for (int i = 0; i < GWS; i++){
//	printf("%f ,", vector1[i]);
    }

    printf("Result: %f\n", result);
    //cleanup(SIGUSR1);
    return 0;
}
<|endoftext|>


<commit_before>/*  This file is part of the KDE project
    Copyright (C) 2005 Matthias Kretz <kretz@kde.org>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License version 2 as published by the Free Software Foundation.

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

    You should have received a copy of the GNU Library General Public License
    along with this library; see the file COPYING.LIB.  If not, write to
    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
    Boston, MA 02110-1301, USA.

*/

#include "backendcapabilities.h"
#include "ifaces/backend.h"
#include "factory.h"
#include "audiosource.h"
#include "videosource.h"

namespace Phonon
{

class BackendCapabilities::Private
{
	public:
		const Ifaces::Backend* backend;
};

static ::KStaticDeleter<BackendCapabilities> sd;

BackendCapabilities* BackendCapabilities::m_self = 0;

BackendCapabilities* BackendCapabilities::self()
{
	if( !m_self )
	{
		m_self = new BackendCapabilities();
		sd.setObject( m_self, m_self );
	}
	return m_self;
}

BackendCapabilities::BackendCapabilities()
	: d( new Private() )
{
	d->backend = Factory::self()->backend();
	connect( Factory::self(), SIGNAL( backendChanged() ), SLOT( slotBackendChanged() ) );
}

BackendCapabilities::~BackendCapabilities()
{
}

bool BackendCapabilities::supportsVideo() const
{
	return d->backend ? d->backend->supportsVideo() : false;
}

bool BackendCapabilities::supportsOSD() const
{
	return d->backend ? d->backend->supportsOSD() : false;
}

bool BackendCapabilities::supportsSubtitles() const
{
	return d->backend ? d->backend->supportsSubtitles() : false;
}

KMimeType::List BackendCapabilities::knownMimeTypes() const
{
	return d->backend ? d->backend->knownMimeTypes() : KMimeType::List();
}

QList<AudioSource> BackendCapabilities::availableAudioSources() const
{
	if( d->backend )
	{
		QList<AudioSource> ret;
		for( int i = 1; i <= d->backend->audioSourceCount(); ++i )
			ret.append( AudioSource( i,
						d->backend->audioSourceName( i ),
						d->backend->audioSourceDescription( i ),
						d->backend->audioSourceVideoIndex( i ) ) );
		return ret;
	}
	return QList<AudioSource>();
}

QList<VideoSource> BackendCapabilities::availableVideoSources() const
{
	if( d->backend )
	{
		QList<VideoSource> ret;
		for( int i = 1; i <= d->backend->videoSourceCount(); ++i )
			ret.append( VideoSource( i,
						d->backend->videoSourceName( i ),
						d->backend->videoSourceDescription( i ),
						d->backend->videoSourceAudioIndex( i ) ) );
		return ret;
	}
	return QList<VideoSource>();
}

QStringList BackendCapabilities::availableAudioEffects() const
{
	return d->backend ? d->backend->availableAudioEffects() : QStringList();
}

QStringList BackendCapabilities::availableVideoEffects() const
{
	return d->backend ? d->backend->availableVideoEffects() : QStringList();
}

void BackendCapabilities::slotBackendChanged()
{
	d->backend = Factory::self()->backend();
	emit capabilitiesChanged();
}

} // namespace Phonon
#include "backendcapabilities.moc"
// vim: sw=4 ts=4 noet
<commit_msg>perhaps now doxygen won't pick up the static deleter variable anymore<commit_after>/*  This file is part of the KDE project
    Copyright (C) 2005 Matthias Kretz <kretz@kde.org>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License version 2 as published by the Free Software Foundation.

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

    You should have received a copy of the GNU Library General Public License
    along with this library; see the file COPYING.LIB.  If not, write to
    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
    Boston, MA 02110-1301, USA.

*/

#include "backendcapabilities.h"
#include "ifaces/backend.h"
#include "factory.h"
#include "audiosource.h"
#include "videosource.h"

static KStaticDeleter<Phonon::BackendCapabilities> sd;

namespace Phonon
{

class BackendCapabilities::Private
{
	public:
		const Ifaces::Backend* backend;
};

BackendCapabilities* BackendCapabilities::m_self = 0;

BackendCapabilities* BackendCapabilities::self()
{
	if( !m_self )
	{
		m_self = new BackendCapabilities();
		::sd.setObject( m_self, m_self );
	}
	return m_self;
}

BackendCapabilities::BackendCapabilities()
	: d( new Private() )
{
	d->backend = Factory::self()->backend();
	connect( Factory::self(), SIGNAL( backendChanged() ), SLOT( slotBackendChanged() ) );
}

BackendCapabilities::~BackendCapabilities()
{
}

bool BackendCapabilities::supportsVideo() const
{
	return d->backend ? d->backend->supportsVideo() : false;
}

bool BackendCapabilities::supportsOSD() const
{
	return d->backend ? d->backend->supportsOSD() : false;
}

bool BackendCapabilities::supportsSubtitles() const
{
	return d->backend ? d->backend->supportsSubtitles() : false;
}

KMimeType::List BackendCapabilities::knownMimeTypes() const
{
	return d->backend ? d->backend->knownMimeTypes() : KMimeType::List();
}

QList<AudioSource> BackendCapabilities::availableAudioSources() const
{
	if( d->backend )
	{
		QList<AudioSource> ret;
		for( int i = 1; i <= d->backend->audioSourceCount(); ++i )
			ret.append( AudioSource( i,
						d->backend->audioSourceName( i ),
						d->backend->audioSourceDescription( i ),
						d->backend->audioSourceVideoIndex( i ) ) );
		return ret;
	}
	return QList<AudioSource>();
}

QList<VideoSource> BackendCapabilities::availableVideoSources() const
{
	if( d->backend )
	{
		QList<VideoSource> ret;
		for( int i = 1; i <= d->backend->videoSourceCount(); ++i )
			ret.append( VideoSource( i,
						d->backend->videoSourceName( i ),
						d->backend->videoSourceDescription( i ),
						d->backend->videoSourceAudioIndex( i ) ) );
		return ret;
	}
	return QList<VideoSource>();
}

QStringList BackendCapabilities::availableAudioEffects() const
{
	return d->backend ? d->backend->availableAudioEffects() : QStringList();
}

QStringList BackendCapabilities::availableVideoEffects() const
{
	return d->backend ? d->backend->availableVideoEffects() : QStringList();
}

void BackendCapabilities::slotBackendChanged()
{
	d->backend = Factory::self()->backend();
	emit capabilitiesChanged();
}

} // namespace Phonon
#include "backendcapabilities.moc"
// vim: sw=4 ts=4 noet
<|endoftext|>


<commit_before>#undef _WIN32_WINNT
#define _WIN32_WINNT 0x0601

#undef WINVER
#define WINVER 0x0601

#include "keyboard-layout-observer.h"

#include <string>
#include <windows.h>

using namespace v8;

std::string ToUTF8(const std::wstring& string) {
  if (string.length() < 1) {
    return std::string();
  }

  // NB: In the pathological case, each character could expand up
  // to 4 bytes in UTF8.
  int cbLen = (string.length()+1) * sizeof(char) * 4;
  char* buf = new char[cbLen];
  int retLen = WideCharToMultiByte(CP_UTF8, 0, string.c_str(), string.length(), buf, cbLen, NULL, NULL);
  buf[retLen] = 0;

  std::string ret;
  ret.assign(buf);
  return ret;
}

void KeyboardLayoutObserver::Init(Handle<Object> target) {
  Nan::HandleScope scope;
  Local<FunctionTemplate> newTemplate = Nan::New<FunctionTemplate>(KeyboardLayoutObserver::New);
  newTemplate->SetClassName(Nan::New<String>("KeyboardLayoutObserver").ToLocalChecked());
  newTemplate->InstanceTemplate()->SetInternalFieldCount(1);
  Local<ObjectTemplate> proto = newTemplate->PrototypeTemplate();

  Nan::SetMethod(proto, "getCurrentKeyboardLayout", KeyboardLayoutObserver::GetCurrentKeyboardLayout);
  Nan::SetMethod(proto, "getCurrentKeyboardLanguage", KeyboardLayoutObserver::GetCurrentKeyboardLanguage);
  Nan::SetMethod(proto, "getInstalledKeyboardLanguages", KeyboardLayoutObserver::GetInstalledKeyboardLanguages);
  target->Set(Nan::New<String>("KeyboardLayoutObserver").ToLocalChecked(), newTemplate->GetFunction());
}

NODE_MODULE(keyboard_layout_observer, KeyboardLayoutObserver::Init)

NAN_METHOD(KeyboardLayoutObserver::New) {
  Nan::HandleScope scope;

  Local<Function> callbackHandle = info[0].As<Function>();
  Nan::Callback *callback = new Nan::Callback(callbackHandle);

  KeyboardLayoutObserver *observer = new KeyboardLayoutObserver(callback);
  observer->Wrap(info.This());
  return;
}

KeyboardLayoutObserver::KeyboardLayoutObserver(Nan::Callback *callback) : callback(callback) {
}

KeyboardLayoutObserver::~KeyboardLayoutObserver() {
  delete callback;
};

void KeyboardLayoutObserver::HandleKeyboardLayoutChanged() {
}

NAN_METHOD(KeyboardLayoutObserver::GetCurrentKeyboardLayout) {
  Nan::HandleScope scope;

  char layoutName[KL_NAMELENGTH];
  if (::GetKeyboardLayoutName(layoutName))
    info.GetReturnValue().Set(Nan::New(layoutName));
  else
    info.GetReturnValue().Set(Nan::Undefined());
}

NAN_METHOD(KeyboardLayoutObserver::GetCurrentKeyboardLanguage) {
  Nan::HandleScope scope;

  HKL layout;
  DWORD dwThreadId = 0;
  HWND hWnd = GetForegroundWindow();

  if (hWnd != NULL) {
    dwThreadId = GetWindowThreadProcessId(hWnd, NULL);
  }

  layout = GetKeyboardLayout(dwThreadId);

  wchar_t buf[LOCALE_NAME_MAX_LENGTH];
  std::wstring wstr;
  LCIDToLocaleName(MAKELCID((UINT)layout & 0xFFFF, SORT_DEFAULT), buf, LOCALE_NAME_MAX_LENGTH, 0);
  wstr.assign(buf);

  std::string str = ToUTF8(wstr);
  info.GetReturnValue().Set(Nan::New<String>(str.data(), str.size())).ToLocalChecked();
}

NAN_METHOD(KeyboardLayoutObserver::GetInstalledKeyboardLanguages) {
  Nan::HandleScope scope;

  int layoutCount = GetKeyboardLayoutList(0, NULL);
  HKL* layouts = new HKL[layoutCount];
  GetKeyboardLayoutList(layoutCount, layouts);

  Local<Array> result = Nan::New<Array>(layoutCount);
  wchar_t buf[LOCALE_NAME_MAX_LENGTH];

  for (int i=0; i < layoutCount; i++) {
    std::wstring wstr;
    LCIDToLocaleName(MAKELCID((UINT)layouts[i] & 0xFFFF, SORT_DEFAULT), buf, LOCALE_NAME_MAX_LENGTH, 0);
    wstr.assign(buf);

    std::string str = ToUTF8(wstr);
    result->Set(i, Nan::New<String>(str.data(), str.size())).ToLocalChecked();
  }

  delete[] layouts;
  info.GetReturnValue().Set(result);
}
<commit_msg>win: Fix calls to ToLocalChecked<commit_after>#undef _WIN32_WINNT
#define _WIN32_WINNT 0x0601

#undef WINVER
#define WINVER 0x0601

#include "keyboard-layout-observer.h"

#include <string>
#include <windows.h>

using namespace v8;

std::string ToUTF8(const std::wstring& string) {
  if (string.length() < 1) {
    return std::string();
  }

  // NB: In the pathological case, each character could expand up
  // to 4 bytes in UTF8.
  int cbLen = (string.length()+1) * sizeof(char) * 4;
  char* buf = new char[cbLen];
  int retLen = WideCharToMultiByte(CP_UTF8, 0, string.c_str(), string.length(), buf, cbLen, NULL, NULL);
  buf[retLen] = 0;

  std::string ret;
  ret.assign(buf);
  return ret;
}

void KeyboardLayoutObserver::Init(Handle<Object> target) {
  Nan::HandleScope scope;
  Local<FunctionTemplate> newTemplate = Nan::New<FunctionTemplate>(KeyboardLayoutObserver::New);
  newTemplate->SetClassName(Nan::New<String>("KeyboardLayoutObserver").ToLocalChecked());
  newTemplate->InstanceTemplate()->SetInternalFieldCount(1);
  Local<ObjectTemplate> proto = newTemplate->PrototypeTemplate();

  Nan::SetMethod(proto, "getCurrentKeyboardLayout", KeyboardLayoutObserver::GetCurrentKeyboardLayout);
  Nan::SetMethod(proto, "getCurrentKeyboardLanguage", KeyboardLayoutObserver::GetCurrentKeyboardLanguage);
  Nan::SetMethod(proto, "getInstalledKeyboardLanguages", KeyboardLayoutObserver::GetInstalledKeyboardLanguages);
  target->Set(Nan::New<String>("KeyboardLayoutObserver").ToLocalChecked(), newTemplate->GetFunction());
}

NODE_MODULE(keyboard_layout_observer, KeyboardLayoutObserver::Init)

NAN_METHOD(KeyboardLayoutObserver::New) {
  Nan::HandleScope scope;

  Local<Function> callbackHandle = info[0].As<Function>();
  Nan::Callback *callback = new Nan::Callback(callbackHandle);

  KeyboardLayoutObserver *observer = new KeyboardLayoutObserver(callback);
  observer->Wrap(info.This());
  return;
}

KeyboardLayoutObserver::KeyboardLayoutObserver(Nan::Callback *callback) : callback(callback) {
}

KeyboardLayoutObserver::~KeyboardLayoutObserver() {
  delete callback;
};

void KeyboardLayoutObserver::HandleKeyboardLayoutChanged() {
}

NAN_METHOD(KeyboardLayoutObserver::GetCurrentKeyboardLayout) {
  Nan::HandleScope scope;

  char layoutName[KL_NAMELENGTH];
  if (::GetKeyboardLayoutName(layoutName))
    info.GetReturnValue().Set(Nan::New(layoutName).ToLocalChecked());
  else
    info.GetReturnValue().Set(Nan::Undefined());
}

NAN_METHOD(KeyboardLayoutObserver::GetCurrentKeyboardLanguage) {
  Nan::HandleScope scope;

  HKL layout;
  DWORD dwThreadId = 0;
  HWND hWnd = GetForegroundWindow();

  if (hWnd != NULL) {
    dwThreadId = GetWindowThreadProcessId(hWnd, NULL);
  }

  layout = GetKeyboardLayout(dwThreadId);

  wchar_t buf[LOCALE_NAME_MAX_LENGTH];
  std::wstring wstr;
  LCIDToLocaleName(MAKELCID((UINT)layout & 0xFFFF, SORT_DEFAULT), buf, LOCALE_NAME_MAX_LENGTH, 0);
  wstr.assign(buf);

  std::string str = ToUTF8(wstr);
  info.GetReturnValue().Set(Nan::New<String>(str.data(), str.size()).ToLocalChecked());
}

NAN_METHOD(KeyboardLayoutObserver::GetInstalledKeyboardLanguages) {
  Nan::HandleScope scope;

  int layoutCount = GetKeyboardLayoutList(0, NULL);
  HKL* layouts = new HKL[layoutCount];
  GetKeyboardLayoutList(layoutCount, layouts);

  Local<Array> result = Nan::New<Array>(layoutCount);
  wchar_t buf[LOCALE_NAME_MAX_LENGTH];

  for (int i=0; i < layoutCount; i++) {
    std::wstring wstr;
    LCIDToLocaleName(MAKELCID((UINT)layouts[i] & 0xFFFF, SORT_DEFAULT), buf, LOCALE_NAME_MAX_LENGTH, 0);
    wstr.assign(buf);

    std::string str = ToUTF8(wstr);
    result->Set(i, Nan::New<String>(str.data(), str.size()).ToLocalChecked());
  }

  delete[] layouts;
  info.GetReturnValue().Set(result);
}
<|endoftext|>


<commit_before>/****************************************************************************
 *
 * SPI Master library for Arduino STM32 + HAL + CubeMX (HALMX).
 *
 * Copyright (c) 2016 by Vassilis Serasidis <info@serasidis.gr>
 * Home: http://www.serasidis.gr
 * email: avrsite@yahoo.gr
 *
 * Arduino_STM32 forum: http://www.stm32duino.com
 *
 * This file is free software; you can redistribute it and/or modify
 * it under the terms of either the GNU General Public License version 2
 * or the GNU Lesser General Public License version 2.1, both as
 * published by the Free Software Foundation.
 *
 ****************************************************************************/

#include <SPI.h>
#include <chip.h>

/* Create an SPIClass instance */
SPIClass SPI    (SPI2);
SPIClass SPI_IMU(SPI1);

void SPISettings::init_AlwaysInline(uint32_t clock, uint8_t bitOrder, uint8_t dataMode)
{
  if (clock >= 50000000 / 2) {
    clockDiv = SPI_CLOCK_DIV2;
  } else if (clock >= 50000000 / 4) {
    clockDiv = SPI_CLOCK_DIV4;
  } else if (clock >= 50000000 / 8) {
    clockDiv = SPI_CLOCK_DIV8;
  } else if (clock >= 50000000 / 16) {
    clockDiv = SPI_CLOCK_DIV16;
  } else if (clock >= 50000000 / 32) {
    clockDiv = SPI_CLOCK_DIV32;
  } else if (clock >= 50000000 / 64) {
    clockDiv = SPI_CLOCK_DIV64;
  } else {
    clockDiv = SPI_CLOCK_DIV64;
  }

  _bitOrder = bitOrder;
  _dataMode = dataMode;
}

SPIClass::SPIClass(SPI_TypeDef *spiPort) {
  _spiPort = spiPort;

  if(spiPort == SPI1)
    _hspi = &hspi1;
  if(spiPort == SPI2)
    _hspi = &hspi2;
}

/**
 * This constructor is written for backward compatibility with Arduino_STM32
 * @Usage example: SPIClass my_spi(2) for using the SPI2 interface
 */
SPIClass::SPIClass(uint8_t spiPort){
  switch(spiPort){
    case 1:
      _spiPort = SPI1;
      _hspi = &hspi1;
    break;

    case 2:
      _spiPort = SPI2;
      _hspi = &hspi2;
    break;
  }
}

void SPIClass::begin(void) {
  init();
}

void SPIClass::init(void){

  _hspi->Instance               = _spiPort;
  _hspi->Init.Mode              = SPI_MODE_MASTER;
  _hspi->Init.Direction         = SPI_DIRECTION_2LINES;
  _hspi->Init.DataSize          = SPI_DATASIZE_8BIT;
  _hspi->Init.CLKPolarity       = SPI_POLARITY_LOW;
  _hspi->Init.CLKPhase          = SPI_PHASE_1EDGE;
  _hspi->Init.NSS               = SPI_NSS_SOFT;
  _hspi->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16; // 4.5 Mbit
  _hspi->Init.FirstBit          = SPI_FIRSTBIT_MSB;
  _hspi->Init.TIMode            = SPI_TIMODE_DISABLE;
  _hspi->Init.CRCCalculation    = SPI_CRCCALCULATION_DISABLE;
  _hspi->Init.CRCPolynomial     = 10;
  HAL_SPI_Init(_hspi);

  if(_spiPort == SPI1){
    __HAL_RCC_SPI1_CLK_ENABLE();
  }

  if(_spiPort == SPI2){
    __HAL_RCC_SPI2_CLK_ENABLE();
  }
}

uint8_t SPIClass::transfer(uint8_t data) const{
  uint8_t ret;
  HAL_SPI_TransmitReceive(_hspi, &data, &ret, 1, 0xffff);
	return ret;
}

uint16_t SPIClass::transfer16(uint16_t data) {
  uint8_t tBuf[2];
  uint8_t rBuf[2];
  uint16_t ret;
  tBuf[1] = (uint8_t)data;
  tBuf[0] = (uint8_t)(data>>8);
  HAL_SPI_TransmitReceive(_hspi, (uint8_t *)&tBuf, (uint8_t *)&rBuf, 2, 0xffff);

  ret = rBuf[0];
  ret <<= 8;
  ret += rBuf[1];

  return ret;
}

void SPIClass::transfer(void *buf, size_t count) {
  HAL_SPI_Transmit(_hspi, (uint8_t *)buf, count, 0xffff);
}

void SPIClass::setBitOrder(uint8_t bitOrder) {
    if (bitOrder == 1)
      _hspi->Init.FirstBit = SPI_FIRSTBIT_MSB;
    else
      _hspi->Init.FirstBit = SPI_FIRSTBIT_LSB;
    HAL_SPI_Init(_hspi);
}

void SPIClass::setClockDivider(uint8_t clockDiv) {
  switch(clockDiv){
    case SPI_CLOCK_DIV2:
      _hspi->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;
    break;
    case SPI_CLOCK_DIV4:
      _hspi->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_4;
    break;
    case SPI_CLOCK_DIV8:
      _hspi->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_8;
    break;
    case SPI_CLOCK_DIV16:
      _hspi->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16;
    break;
    case SPI_CLOCK_DIV32:
      _hspi->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_32;
    break;
    case SPI_CLOCK_DIV64:
      _hspi->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_64;
    break;
    case SPI_CLOCK_DIV128:
      _hspi->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_128;
    break;
    case SPI_CLOCK_DIV256:
      _hspi->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256;
    break;
  }
  HAL_SPI_Init(_hspi);
}

void SPIClass::setDataMode(uint8_t dataMode){

  switch( dataMode )
  {
    // CPOL=0, CPHA=0
    case SPI_MODE0:
      _hspi->Init.CLKPolarity = SPI_POLARITY_LOW;
      _hspi->Init.CLKPhase    = SPI_PHASE_1EDGE;
      HAL_SPI_Init(_hspi);
      break;

    // CPOL=0, CPHA=1
    case SPI_MODE1:
      _hspi->Init.CLKPolarity = SPI_POLARITY_LOW;
      _hspi->Init.CLKPhase    = SPI_PHASE_2EDGE;
      HAL_SPI_Init(_hspi);
      break;

    // CPOL=1, CPHA=0
    case SPI_MODE2:
      _hspi->Init.CLKPolarity  = SPI_POLARITY_HIGH;
      _hspi->Init.CLKPhase    = SPI_PHASE_1EDGE;
      HAL_SPI_Init(_hspi);
      break;

    // CPOL=1, CPHA=1
    case SPI_MODE3:
      _hspi->Init.CLKPolarity  = SPI_POLARITY_HIGH;
      _hspi->Init.CLKPhase    = SPI_PHASE_2EDGE;
      HAL_SPI_Init(_hspi);
      break;
  }
}
<commit_msg>Fixed SPI transfer bug.<commit_after>/****************************************************************************
 *
 * SPI Master library for Arduino STM32 + HAL + CubeMX (HALMX).
 *
 * Copyright (c) 2016 by Vassilis Serasidis <info@serasidis.gr>
 * Home: http://www.serasidis.gr
 * email: avrsite@yahoo.gr
 *
 * Arduino_STM32 forum: http://www.stm32duino.com
 *
 * This file is free software; you can redistribute it and/or modify
 * it under the terms of either the GNU General Public License version 2
 * or the GNU Lesser General Public License version 2.1, both as
 * published by the Free Software Foundation.
 *
 ****************************************************************************/

#include <SPI.h>
#include <chip.h>

/* Create an SPIClass instance */
SPIClass SPI    (SPI2);
SPIClass SPI_IMU(SPI1);

void SPISettings::init_AlwaysInline(uint32_t clock, uint8_t bitOrder, uint8_t dataMode)
{
  if (clock >= 50000000 / 2) {
    clockDiv = SPI_CLOCK_DIV2;
  } else if (clock >= 50000000 / 4) {
    clockDiv = SPI_CLOCK_DIV4;
  } else if (clock >= 50000000 / 8) {
    clockDiv = SPI_CLOCK_DIV8;
  } else if (clock >= 50000000 / 16) {
    clockDiv = SPI_CLOCK_DIV16;
  } else if (clock >= 50000000 / 32) {
    clockDiv = SPI_CLOCK_DIV32;
  } else if (clock >= 50000000 / 64) {
    clockDiv = SPI_CLOCK_DIV64;
  } else {
    clockDiv = SPI_CLOCK_DIV64;
  }

  _bitOrder = bitOrder;
  _dataMode = dataMode;
}

SPIClass::SPIClass(SPI_TypeDef *spiPort) {
  _spiPort = spiPort;

  if(spiPort == SPI1)
    _hspi = &hspi1;
  if(spiPort == SPI2)
    _hspi = &hspi2;
}

/**
 * This constructor is written for backward compatibility with Arduino_STM32
 * @Usage example: SPIClass my_spi(2) for using the SPI2 interface
 */
SPIClass::SPIClass(uint8_t spiPort){
  switch(spiPort){
    case 1:
      _spiPort = SPI1;
      _hspi = &hspi1;
    break;

    case 2:
      _spiPort = SPI2;
      _hspi = &hspi2;
    break;
  }
}

void SPIClass::begin(void) {
  init();
}

void SPIClass::init(void){

  _hspi->Instance               = _spiPort;
  _hspi->Init.Mode              = SPI_MODE_MASTER;
  _hspi->Init.Direction         = SPI_DIRECTION_2LINES;
  _hspi->Init.DataSize          = SPI_DATASIZE_8BIT;
  _hspi->Init.CLKPolarity       = SPI_POLARITY_LOW;
  _hspi->Init.CLKPhase          = SPI_PHASE_1EDGE;
  _hspi->Init.NSS               = SPI_NSS_SOFT;
  _hspi->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16; // 4.5 Mbit
  _hspi->Init.FirstBit          = SPI_FIRSTBIT_MSB;
  _hspi->Init.TIMode            = SPI_TIMODE_DISABLE;
  _hspi->Init.CRCCalculation    = SPI_CRCCALCULATION_DISABLE;
  _hspi->Init.CRCPolynomial     = 10;
  HAL_SPI_Init(_hspi);

  if(_spiPort == SPI1){
    __HAL_RCC_SPI1_CLK_ENABLE();
  }

  if(_spiPort == SPI2){
    __HAL_RCC_SPI2_CLK_ENABLE();
  }
}

uint8_t SPIClass::transfer(uint8_t data) const{
  uint8_t ret;
  HAL_SPI_TransmitReceive(_hspi, &data, &ret, 1, 0xffff);
	return ret;
}

uint16_t SPIClass::transfer16(uint16_t data) {
  uint8_t tBuf[2];
  uint8_t rBuf[2];
  uint16_t ret;
  tBuf[1] = (uint8_t)data;
  tBuf[0] = (uint8_t)(data>>8);
  HAL_SPI_TransmitReceive(_hspi, (uint8_t *)&tBuf, (uint8_t *)&rBuf, 2, 0xffff);

  ret = rBuf[0];
  ret <<= 8;
  ret += rBuf[1];

  return ret;
}

void SPIClass::transfer(void *buf, size_t count) {
  //HAL_SPI_Transmit(_hspi, (uint8_t *)buf, count, 0xffff);
  //HAL_SPI_TransmitReceive(_hspi, (uint8_t *)buf, (uint8_t *)buf, count, 0xffff);
  int i;
  uint8_t *pbuf = (uint8_t *)buf;

  for( i=0; i<count; i++ )
  {
    pbuf[i] = transfer(0xFF);
  }
}

void SPIClass::setBitOrder(uint8_t bitOrder) {
    if (bitOrder == 1)
      _hspi->Init.FirstBit = SPI_FIRSTBIT_MSB;
    else
      _hspi->Init.FirstBit = SPI_FIRSTBIT_LSB;
    HAL_SPI_Init(_hspi);
}

void SPIClass::setClockDivider(uint8_t clockDiv) {
  switch(clockDiv){
    case SPI_CLOCK_DIV2:
      _hspi->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;
    break;
    case SPI_CLOCK_DIV4:
      _hspi->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_4;
    break;
    case SPI_CLOCK_DIV8:
      _hspi->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_8;
    break;
    case SPI_CLOCK_DIV16:
      _hspi->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16;
    break;
    case SPI_CLOCK_DIV32:
      _hspi->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_32;
    break;
    case SPI_CLOCK_DIV64:
      _hspi->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_64;
    break;
    case SPI_CLOCK_DIV128:
      _hspi->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_128;
    break;
    case SPI_CLOCK_DIV256:
      _hspi->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256;
    break;
  }
  HAL_SPI_Init(_hspi);
}

void SPIClass::setDataMode(uint8_t dataMode){

  switch( dataMode )
  {
    // CPOL=0, CPHA=0
    case SPI_MODE0:
      _hspi->Init.CLKPolarity = SPI_POLARITY_LOW;
      _hspi->Init.CLKPhase    = SPI_PHASE_1EDGE;
      HAL_SPI_Init(_hspi);
      break;

    // CPOL=0, CPHA=1
    case SPI_MODE1:
      _hspi->Init.CLKPolarity = SPI_POLARITY_LOW;
      _hspi->Init.CLKPhase    = SPI_PHASE_2EDGE;
      HAL_SPI_Init(_hspi);
      break;

    // CPOL=1, CPHA=0
    case SPI_MODE2:
      _hspi->Init.CLKPolarity  = SPI_POLARITY_HIGH;
      _hspi->Init.CLKPhase    = SPI_PHASE_1EDGE;
      HAL_SPI_Init(_hspi);
      break;

    // CPOL=1, CPHA=1
    case SPI_MODE3:
      _hspi->Init.CLKPolarity  = SPI_POLARITY_HIGH;
      _hspi->Init.CLKPhase    = SPI_PHASE_2EDGE;
      HAL_SPI_Init(_hspi);
      break;
  }
}
<|endoftext|>


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

#include "base/lock_impl.h"

#include <errno.h>

#include "base/logging.h"

LockImpl::LockImpl() {
  pthread_mutexattr_t mta;
  int rv = pthread_mutexattr_init(&mta);
  DCHECK(rv == 0);
  //rv = pthread_mutexattr_settype(&mta, PTHREAD_MUTEX_RECURSIVE);
  DCHECK(rv == 0);
  rv = pthread_mutex_init(&os_lock_, &mta);
  DCHECK(rv == 0);
  rv = pthread_mutexattr_destroy(&mta);
  DCHECK(rv == 0);
}

LockImpl::~LockImpl() {
  int rv = pthread_mutex_destroy(&os_lock_);
  DCHECK(rv == 0);
}

bool LockImpl::Try() {
  int rv = pthread_mutex_trylock(&os_lock_);
  DCHECK(rv == 0 || rv == EBUSY);
  return rv == 0;
}

void LockImpl::Lock() {
  int rv = pthread_mutex_lock(&os_lock_);
  DCHECK(rv == 0);
}

void LockImpl::Unlock() {
  int rv = pthread_mutex_unlock(&os_lock_);
  DCHECK(rv == 0);
}

<commit_msg>Enable error checking on Posix locks in debug, and make release lock creation do a little bit less work.  Based on suggestions by Gaetano Mendola. Review URL: http://codereview.chromium.org/6038<commit_after>// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/lock_impl.h"

#include <errno.h>

#include "base/logging.h"

LockImpl::LockImpl() {
#ifndef NDEBUG
  // In debug, setup attributes for lock error checking.
  pthread_mutexattr_t mta;
  int rv = pthread_mutexattr_init(&mta);
  DCHECK(rv == 0);
  rv = pthread_mutexattr_settype(&mta, PTHREAD_MUTEX_ERRORCHECK);
  DCHECK(rv == 0);
  rv = pthread_mutex_init(&os_lock_, &mta);
  DCHECK(rv == 0);
  rv = pthread_mutexattr_destroy(&mta);
  DCHECK(rv == 0);
#else
  // In release, go with the default lock attributes.
  pthread_mutex_init(&os_lock_, NULL);
#endif
}

LockImpl::~LockImpl() {
  int rv = pthread_mutex_destroy(&os_lock_);
  DCHECK(rv == 0);
}

bool LockImpl::Try() {
  int rv = pthread_mutex_trylock(&os_lock_);
  DCHECK(rv == 0 || rv == EBUSY);
  return rv == 0;
}

void LockImpl::Lock() {
  int rv = pthread_mutex_lock(&os_lock_);
  DCHECK(rv == 0);
}

void LockImpl::Unlock() {
  int rv = pthread_mutex_unlock(&os_lock_);
  DCHECK(rv == 0);
}

<|endoftext|>


<commit_before>/*
 * libjingle
 * Copyright 2004--2011, Google Inc.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *  1. Redistributions of source code must retain the above copyright notice,
 *     this list of conditions and the following disclaimer.
 *  2. Redistributions in binary form must reproduce the above copyright notice,
 *     this list of conditions and the following disclaimer in the documentation
 *     and/or other materials provided with the distribution.
 *  3. The name of the author may not be used to endorse or promote products
 *     derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "talk/base/asyncinvoker.h"
#include "talk/base/asyncudpsocket.h"
#include "talk/base/event.h"
#include "talk/base/gunit.h"
#include "talk/base/physicalsocketserver.h"
#include "talk/base/socketaddress.h"
#include "talk/base/thread.h"

#ifdef WIN32
#include <comdef.h>  // NOLINT
#endif

using namespace talk_base;

const int MAX = 65536;

// Generates a sequence of numbers (collaboratively).
class TestGenerator {
 public:
  TestGenerator() : last(0), count(0) {}

  int Next(int prev) {
    int result = prev + last;
    last = result;
    count += 1;
    return result;
  }

  int last;
  int count;
};

struct TestMessage : public MessageData {
  explicit TestMessage(int v) : value(v) {}
  virtual ~TestMessage() {}

  int value;
};

// Receives on a socket and sends by posting messages.
class SocketClient : public TestGenerator, public sigslot::has_slots<> {
 public:
  SocketClient(AsyncSocket* socket, const SocketAddress& addr,
               Thread* post_thread, MessageHandler* phandler)
      : socket_(AsyncUDPSocket::Create(socket, addr)),
        post_thread_(post_thread),
        post_handler_(phandler) {
    socket_->SignalReadPacket.connect(this, &SocketClient::OnPacket);
  }

  ~SocketClient() {
    delete socket_;
  }

  SocketAddress address() const { return socket_->GetLocalAddress(); }

  void OnPacket(AsyncPacketSocket* socket, const char* buf, size_t size,
                const SocketAddress& remote_addr,
                const PacketTime& packet_time) {
    EXPECT_EQ(size, sizeof(uint32));
    uint32 prev = reinterpret_cast<const uint32*>(buf)[0];
    uint32 result = Next(prev);

    //socket_->set_readable(last < MAX);
    post_thread_->PostDelayed(200, post_handler_, 0, new TestMessage(result));
  }

 private:
  AsyncUDPSocket* socket_;
  Thread* post_thread_;
  MessageHandler* post_handler_;
};

// Receives messages and sends on a socket.
class MessageClient : public MessageHandler, public TestGenerator {
 public:
  MessageClient(Thread* pth, Socket* socket)
      : thread_(pth), socket_(socket) {
  }

  virtual ~MessageClient() {
    delete socket_;
  }

  virtual void OnMessage(Message *pmsg) {
    TestMessage* msg = static_cast<TestMessage*>(pmsg->pdata);
    int result = Next(msg->value);
    EXPECT_GE(socket_->Send(&result, sizeof(result)), 0);
    delete msg;
  }

 private:
  Thread* thread_;
  Socket* socket_;
};

class CustomThread : public talk_base::Thread {
 public:
  CustomThread() {}
  virtual ~CustomThread() { Stop(); }
  bool Start() { return false; }
};

// A thread that does nothing when it runs and signals an event
// when it is destroyed.
class SignalWhenDestroyedThread : public Thread {
 public:
  SignalWhenDestroyedThread(Event* event)
      : event_(event) {
  }

  virtual ~SignalWhenDestroyedThread() {
    Stop();
    event_->Set();
  }

  virtual void Run() {
    // Do nothing.
  }

 private:
  Event* event_;
};

// Function objects to test Thread::Invoke.
struct FunctorA {
  int operator()() { return 42; }
};
class FunctorB {
 public:
  explicit FunctorB(bool* flag) : flag_(flag) {}
  void operator()() { if (flag_) *flag_ = true; }
 private:
  bool* flag_;
};
struct FunctorC {
  int operator()() {
    Thread::Current()->ProcessMessages(50);
    return 24;
  }
};

// See: https://code.google.com/p/webrtc/issues/detail?id=2409
TEST(ThreadTest, DISABLED_Main) {
  const SocketAddress addr("127.0.0.1", 0);

  // Create the messaging client on its own thread.
  Thread th1;
  Socket* socket = th1.socketserver()->CreateAsyncSocket(addr.family(),
                                                         SOCK_DGRAM);
  MessageClient msg_client(&th1, socket);

  // Create the socket client on its own thread.
  Thread th2;
  AsyncSocket* asocket =
      th2.socketserver()->CreateAsyncSocket(addr.family(), SOCK_DGRAM);
  SocketClient sock_client(asocket, addr, &th1, &msg_client);

  socket->Connect(sock_client.address());

  th1.Start();
  th2.Start();

  // Get the messages started.
  th1.PostDelayed(100, &msg_client, 0, new TestMessage(1));

  // Give the clients a little while to run.
  // Messages will be processed at 100, 300, 500, 700, 900.
  Thread* th_main = Thread::Current();
  th_main->ProcessMessages(1000);

  // Stop the sending client. Give the receiver a bit longer to run, in case
  // it is running on a machine that is under load (e.g. the build machine).
  th1.Stop();
  th_main->ProcessMessages(200);
  th2.Stop();

  // Make sure the results were correct
  EXPECT_EQ(5, msg_client.count);
  EXPECT_EQ(34, msg_client.last);
  EXPECT_EQ(5, sock_client.count);
  EXPECT_EQ(55, sock_client.last);
}

// Test that setting thread names doesn't cause a malfunction.
// There's no easy way to verify the name was set properly at this time.
TEST(ThreadTest, Names) {
  // Default name
  Thread *thread;
  thread = new Thread();
  EXPECT_TRUE(thread->Start());
  thread->Stop();
  delete thread;
  thread = new Thread();
  // Name with no object parameter
  EXPECT_TRUE(thread->SetName("No object", NULL));
  EXPECT_TRUE(thread->Start());
  thread->Stop();
  delete thread;
  // Really long name
  thread = new Thread();
  EXPECT_TRUE(thread->SetName("Abcdefghijklmnopqrstuvwxyz1234567890", this));
  EXPECT_TRUE(thread->Start());
  thread->Stop();
  delete thread;
}

// Test that setting thread priorities doesn't cause a malfunction.
// There's no easy way to verify the priority was set properly at this time.
TEST(ThreadTest, Priorities) {
  Thread *thread;
  thread = new Thread();
  EXPECT_TRUE(thread->SetPriority(PRIORITY_HIGH));
  EXPECT_TRUE(thread->Start());
  thread->Stop();
  delete thread;
  thread = new Thread();
  EXPECT_TRUE(thread->SetPriority(PRIORITY_ABOVE_NORMAL));
  EXPECT_TRUE(thread->Start());
  thread->Stop();
  delete thread;

  thread = new Thread();
  EXPECT_TRUE(thread->Start());
#ifdef WIN32
  EXPECT_TRUE(thread->SetPriority(PRIORITY_ABOVE_NORMAL));
#else
  EXPECT_FALSE(thread->SetPriority(PRIORITY_ABOVE_NORMAL));
#endif
  thread->Stop();
  delete thread;

}

TEST(ThreadTest, Wrap) {
  Thread* current_thread = Thread::Current();
  current_thread->UnwrapCurrent();
  CustomThread* cthread = new CustomThread();
  EXPECT_TRUE(cthread->WrapCurrent());
  EXPECT_TRUE(cthread->started());
  EXPECT_FALSE(cthread->IsOwned());
  cthread->UnwrapCurrent();
  EXPECT_FALSE(cthread->started());
  delete cthread;
  current_thread->WrapCurrent();
}

// Test that calling Release on a thread causes it to self-destruct when
// it's finished running
TEST(ThreadTest, Release) {
  scoped_ptr<Event> event(new Event(true, false));
  // Ensure the event is initialized.
  event->Reset();

  Thread* thread = new SignalWhenDestroyedThread(event.get());
  thread->Start();
  thread->Release();

  // The event should get signaled when the thread completes, which should
  // be nearly instantaneous, since it doesn't do anything.  For safety,
  // give it 3 seconds in case the machine is under load.
  bool signaled = event->Wait(3000);
  EXPECT_TRUE(signaled);
}

TEST(ThreadTest, Invoke) {
  // Create and start the thread.
  Thread thread;
  thread.Start();
  // Try calling functors.
  EXPECT_EQ(42, thread.Invoke<int>(FunctorA()));
  bool called = false;
  FunctorB f2(&called);
  thread.Invoke<void>(f2);
  EXPECT_TRUE(called);
  // Try calling bare functions.
  struct LocalFuncs {
    static int Func1() { return 999; }
    static void Func2() {}
  };
  EXPECT_EQ(999, thread.Invoke<int>(&LocalFuncs::Func1));
  thread.Invoke<void>(&LocalFuncs::Func2);
}

class AsyncInvokeTest : public testing::Test {
 public:
  void IntCallback(int value) {
    EXPECT_EQ(expected_thread_, Thread::Current());
    int_value_ = value;
  }
  void AsyncInvokeIntCallback(AsyncInvoker* invoker, Thread* thread) {
    expected_thread_ = thread;
    invoker->AsyncInvoke(thread, FunctorC(),
                         &AsyncInvokeTest::IntCallback,
                         static_cast<AsyncInvokeTest*>(this));
    invoke_started_.Set();
  }
  void SetExpectedThreadForIntCallback(Thread* thread) {
    expected_thread_ = thread;
  }

 protected:
  enum { kWaitTimeout = 1000 };
  AsyncInvokeTest()
      : int_value_(0),
        invoke_started_(true, false),
        expected_thread_(NULL) {}

  int int_value_;
  Event invoke_started_;
  Thread* expected_thread_;
};

TEST_F(AsyncInvokeTest, FireAndForget) {
  AsyncInvoker invoker;
  // Create and start the thread.
  Thread thread;
  thread.Start();
  // Try calling functor.
  bool called = false;
  invoker.AsyncInvoke<void>(&thread, FunctorB(&called));
  EXPECT_TRUE_WAIT(called, kWaitTimeout);
}

TEST_F(AsyncInvokeTest, WithCallback) {
  AsyncInvoker invoker;
  // Create and start the thread.
  Thread thread;
  thread.Start();
  // Try calling functor.
  SetExpectedThreadForIntCallback(Thread::Current());
  invoker.AsyncInvoke(&thread, FunctorA(),
                      &AsyncInvokeTest::IntCallback,
                      static_cast<AsyncInvokeTest*>(this));
  EXPECT_EQ_WAIT(42, int_value_, kWaitTimeout);
}

TEST_F(AsyncInvokeTest, CancelInvoker) {
  // Create and start the thread.
  Thread thread;
  thread.Start();
  // Try destroying invoker during call.
  {
    AsyncInvoker invoker;
    invoker.AsyncInvoke(&thread, FunctorC(),
                        &AsyncInvokeTest::IntCallback,
                        static_cast<AsyncInvokeTest*>(this));
  }
  // With invoker gone, callback should be cancelled.
  Thread::Current()->ProcessMessages(kWaitTimeout);
  EXPECT_EQ(0, int_value_);
}

TEST_F(AsyncInvokeTest, CancelCallingThread) {
  AsyncInvoker invoker;
  { // Create and start the thread.
    Thread thread;
    thread.Start();
    // Try calling functor.
    thread.Invoke<void>(Bind(&AsyncInvokeTest::AsyncInvokeIntCallback,
                             static_cast<AsyncInvokeTest*>(this),
                             &invoker, Thread::Current()));
    // Wait for the call to begin.
    ASSERT_TRUE(invoke_started_.Wait(kWaitTimeout));
  }
  // Calling thread is gone. Return message shouldn't happen.
  Thread::Current()->ProcessMessages(kWaitTimeout);
  EXPECT_EQ(0, int_value_);
}

TEST_F(AsyncInvokeTest, KillInvokerBeforeExecute) {
  Thread thread;
  thread.Start();
  {
    AsyncInvoker invoker;
    // Try calling functor.
    thread.Invoke<void>(Bind(&AsyncInvokeTest::AsyncInvokeIntCallback,
                             static_cast<AsyncInvokeTest*>(this),
                             &invoker, Thread::Current()));
    // Wait for the call to begin.
    ASSERT_TRUE(invoke_started_.Wait(kWaitTimeout));
  }
  // Invoker is destroyed. Function should not execute.
  Thread::Current()->ProcessMessages(kWaitTimeout);
  EXPECT_EQ(0, int_value_);
}

TEST_F(AsyncInvokeTest, Flush) {
  AsyncInvoker invoker;
  bool flag1 = false;
  bool flag2 = false;
  // Queue two async calls to the current thread.
  invoker.AsyncInvoke<void>(Thread::Current(),
                            FunctorB(&flag1));
  invoker.AsyncInvoke<void>(Thread::Current(),
                            FunctorB(&flag2));
  // Because we haven't pumped messages, these should not have run yet.
  EXPECT_FALSE(flag1);
  EXPECT_FALSE(flag2);
  // Force them to run now.
  invoker.Flush(Thread::Current());
  EXPECT_TRUE(flag1);
  EXPECT_TRUE(flag2);
}

TEST_F(AsyncInvokeTest, FlushWithIds) {
  AsyncInvoker invoker;
  bool flag1 = false;
  bool flag2 = false;
  // Queue two async calls to the current thread, one with a message id.
  invoker.AsyncInvoke<void>(Thread::Current(),
                            FunctorB(&flag1),
                            5);
  invoker.AsyncInvoke<void>(Thread::Current(),
                            FunctorB(&flag2));
  // Because we haven't pumped messages, these should not have run yet.
  EXPECT_FALSE(flag1);
  EXPECT_FALSE(flag2);
  // Execute pending calls with id == 5.
  invoker.Flush(Thread::Current(), 5);
  EXPECT_TRUE(flag1);
  EXPECT_FALSE(flag2);
  flag1 = false;
  // Execute all pending calls. The id == 5 call should not execute again.
  invoker.Flush(Thread::Current());
  EXPECT_FALSE(flag1);
  EXPECT_TRUE(flag2);
}

#ifdef WIN32
class ComThreadTest : public testing::Test, public MessageHandler {
 public:
  ComThreadTest() : done_(false) {}
 protected:
  virtual void OnMessage(Message* message) {
    HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
    // S_FALSE means the thread was already inited for a multithread apartment.
    EXPECT_EQ(S_FALSE, hr);
    if (SUCCEEDED(hr)) {
      CoUninitialize();
    }
    done_ = true;
  }
  bool done_;
};

TEST_F(ComThreadTest, ComInited) {
  Thread* thread = new ComThread();
  EXPECT_TRUE(thread->Start());
  thread->Post(this, 0);
  EXPECT_TRUE_WAIT(done_, 1000);
  delete thread;
}
#endif
<commit_msg>Disable AsyncInvokeTest.CancelInvoker test<commit_after>/*
 * libjingle
 * Copyright 2004--2011, Google Inc.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *  1. Redistributions of source code must retain the above copyright notice,
 *     this list of conditions and the following disclaimer.
 *  2. Redistributions in binary form must reproduce the above copyright notice,
 *     this list of conditions and the following disclaimer in the documentation
 *     and/or other materials provided with the distribution.
 *  3. The name of the author may not be used to endorse or promote products
 *     derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "talk/base/asyncinvoker.h"
#include "talk/base/asyncudpsocket.h"
#include "talk/base/event.h"
#include "talk/base/gunit.h"
#include "talk/base/physicalsocketserver.h"
#include "talk/base/socketaddress.h"
#include "talk/base/thread.h"

#ifdef WIN32
#include <comdef.h>  // NOLINT
#endif

using namespace talk_base;

const int MAX = 65536;

// Generates a sequence of numbers (collaboratively).
class TestGenerator {
 public:
  TestGenerator() : last(0), count(0) {}

  int Next(int prev) {
    int result = prev + last;
    last = result;
    count += 1;
    return result;
  }

  int last;
  int count;
};

struct TestMessage : public MessageData {
  explicit TestMessage(int v) : value(v) {}
  virtual ~TestMessage() {}

  int value;
};

// Receives on a socket and sends by posting messages.
class SocketClient : public TestGenerator, public sigslot::has_slots<> {
 public:
  SocketClient(AsyncSocket* socket, const SocketAddress& addr,
               Thread* post_thread, MessageHandler* phandler)
      : socket_(AsyncUDPSocket::Create(socket, addr)),
        post_thread_(post_thread),
        post_handler_(phandler) {
    socket_->SignalReadPacket.connect(this, &SocketClient::OnPacket);
  }

  ~SocketClient() {
    delete socket_;
  }

  SocketAddress address() const { return socket_->GetLocalAddress(); }

  void OnPacket(AsyncPacketSocket* socket, const char* buf, size_t size,
                const SocketAddress& remote_addr,
                const PacketTime& packet_time) {
    EXPECT_EQ(size, sizeof(uint32));
    uint32 prev = reinterpret_cast<const uint32*>(buf)[0];
    uint32 result = Next(prev);

    //socket_->set_readable(last < MAX);
    post_thread_->PostDelayed(200, post_handler_, 0, new TestMessage(result));
  }

 private:
  AsyncUDPSocket* socket_;
  Thread* post_thread_;
  MessageHandler* post_handler_;
};

// Receives messages and sends on a socket.
class MessageClient : public MessageHandler, public TestGenerator {
 public:
  MessageClient(Thread* pth, Socket* socket)
      : thread_(pth), socket_(socket) {
  }

  virtual ~MessageClient() {
    delete socket_;
  }

  virtual void OnMessage(Message *pmsg) {
    TestMessage* msg = static_cast<TestMessage*>(pmsg->pdata);
    int result = Next(msg->value);
    EXPECT_GE(socket_->Send(&result, sizeof(result)), 0);
    delete msg;
  }

 private:
  Thread* thread_;
  Socket* socket_;
};

class CustomThread : public talk_base::Thread {
 public:
  CustomThread() {}
  virtual ~CustomThread() { Stop(); }
  bool Start() { return false; }
};

// A thread that does nothing when it runs and signals an event
// when it is destroyed.
class SignalWhenDestroyedThread : public Thread {
 public:
  SignalWhenDestroyedThread(Event* event)
      : event_(event) {
  }

  virtual ~SignalWhenDestroyedThread() {
    Stop();
    event_->Set();
  }

  virtual void Run() {
    // Do nothing.
  }

 private:
  Event* event_;
};

// Function objects to test Thread::Invoke.
struct FunctorA {
  int operator()() { return 42; }
};
class FunctorB {
 public:
  explicit FunctorB(bool* flag) : flag_(flag) {}
  void operator()() { if (flag_) *flag_ = true; }
 private:
  bool* flag_;
};
struct FunctorC {
  int operator()() {
    Thread::Current()->ProcessMessages(50);
    return 24;
  }
};

// See: https://code.google.com/p/webrtc/issues/detail?id=2409
TEST(ThreadTest, DISABLED_Main) {
  const SocketAddress addr("127.0.0.1", 0);

  // Create the messaging client on its own thread.
  Thread th1;
  Socket* socket = th1.socketserver()->CreateAsyncSocket(addr.family(),
                                                         SOCK_DGRAM);
  MessageClient msg_client(&th1, socket);

  // Create the socket client on its own thread.
  Thread th2;
  AsyncSocket* asocket =
      th2.socketserver()->CreateAsyncSocket(addr.family(), SOCK_DGRAM);
  SocketClient sock_client(asocket, addr, &th1, &msg_client);

  socket->Connect(sock_client.address());

  th1.Start();
  th2.Start();

  // Get the messages started.
  th1.PostDelayed(100, &msg_client, 0, new TestMessage(1));

  // Give the clients a little while to run.
  // Messages will be processed at 100, 300, 500, 700, 900.
  Thread* th_main = Thread::Current();
  th_main->ProcessMessages(1000);

  // Stop the sending client. Give the receiver a bit longer to run, in case
  // it is running on a machine that is under load (e.g. the build machine).
  th1.Stop();
  th_main->ProcessMessages(200);
  th2.Stop();

  // Make sure the results were correct
  EXPECT_EQ(5, msg_client.count);
  EXPECT_EQ(34, msg_client.last);
  EXPECT_EQ(5, sock_client.count);
  EXPECT_EQ(55, sock_client.last);
}

// Test that setting thread names doesn't cause a malfunction.
// There's no easy way to verify the name was set properly at this time.
TEST(ThreadTest, Names) {
  // Default name
  Thread *thread;
  thread = new Thread();
  EXPECT_TRUE(thread->Start());
  thread->Stop();
  delete thread;
  thread = new Thread();
  // Name with no object parameter
  EXPECT_TRUE(thread->SetName("No object", NULL));
  EXPECT_TRUE(thread->Start());
  thread->Stop();
  delete thread;
  // Really long name
  thread = new Thread();
  EXPECT_TRUE(thread->SetName("Abcdefghijklmnopqrstuvwxyz1234567890", this));
  EXPECT_TRUE(thread->Start());
  thread->Stop();
  delete thread;
}

// Test that setting thread priorities doesn't cause a malfunction.
// There's no easy way to verify the priority was set properly at this time.
TEST(ThreadTest, Priorities) {
  Thread *thread;
  thread = new Thread();
  EXPECT_TRUE(thread->SetPriority(PRIORITY_HIGH));
  EXPECT_TRUE(thread->Start());
  thread->Stop();
  delete thread;
  thread = new Thread();
  EXPECT_TRUE(thread->SetPriority(PRIORITY_ABOVE_NORMAL));
  EXPECT_TRUE(thread->Start());
  thread->Stop();
  delete thread;

  thread = new Thread();
  EXPECT_TRUE(thread->Start());
#ifdef WIN32
  EXPECT_TRUE(thread->SetPriority(PRIORITY_ABOVE_NORMAL));
#else
  EXPECT_FALSE(thread->SetPriority(PRIORITY_ABOVE_NORMAL));
#endif
  thread->Stop();
  delete thread;

}

TEST(ThreadTest, Wrap) {
  Thread* current_thread = Thread::Current();
  current_thread->UnwrapCurrent();
  CustomThread* cthread = new CustomThread();
  EXPECT_TRUE(cthread->WrapCurrent());
  EXPECT_TRUE(cthread->started());
  EXPECT_FALSE(cthread->IsOwned());
  cthread->UnwrapCurrent();
  EXPECT_FALSE(cthread->started());
  delete cthread;
  current_thread->WrapCurrent();
}

// Test that calling Release on a thread causes it to self-destruct when
// it's finished running
TEST(ThreadTest, Release) {
  scoped_ptr<Event> event(new Event(true, false));
  // Ensure the event is initialized.
  event->Reset();

  Thread* thread = new SignalWhenDestroyedThread(event.get());
  thread->Start();
  thread->Release();

  // The event should get signaled when the thread completes, which should
  // be nearly instantaneous, since it doesn't do anything.  For safety,
  // give it 3 seconds in case the machine is under load.
  bool signaled = event->Wait(3000);
  EXPECT_TRUE(signaled);
}

TEST(ThreadTest, Invoke) {
  // Create and start the thread.
  Thread thread;
  thread.Start();
  // Try calling functors.
  EXPECT_EQ(42, thread.Invoke<int>(FunctorA()));
  bool called = false;
  FunctorB f2(&called);
  thread.Invoke<void>(f2);
  EXPECT_TRUE(called);
  // Try calling bare functions.
  struct LocalFuncs {
    static int Func1() { return 999; }
    static void Func2() {}
  };
  EXPECT_EQ(999, thread.Invoke<int>(&LocalFuncs::Func1));
  thread.Invoke<void>(&LocalFuncs::Func2);
}

class AsyncInvokeTest : public testing::Test {
 public:
  void IntCallback(int value) {
    EXPECT_EQ(expected_thread_, Thread::Current());
    int_value_ = value;
  }
  void AsyncInvokeIntCallback(AsyncInvoker* invoker, Thread* thread) {
    expected_thread_ = thread;
    invoker->AsyncInvoke(thread, FunctorC(),
                         &AsyncInvokeTest::IntCallback,
                         static_cast<AsyncInvokeTest*>(this));
    invoke_started_.Set();
  }
  void SetExpectedThreadForIntCallback(Thread* thread) {
    expected_thread_ = thread;
  }

 protected:
  enum { kWaitTimeout = 1000 };
  AsyncInvokeTest()
      : int_value_(0),
        invoke_started_(true, false),
        expected_thread_(NULL) {}

  int int_value_;
  Event invoke_started_;
  Thread* expected_thread_;
};

TEST_F(AsyncInvokeTest, FireAndForget) {
  AsyncInvoker invoker;
  // Create and start the thread.
  Thread thread;
  thread.Start();
  // Try calling functor.
  bool called = false;
  invoker.AsyncInvoke<void>(&thread, FunctorB(&called));
  EXPECT_TRUE_WAIT(called, kWaitTimeout);
}

TEST_F(AsyncInvokeTest, WithCallback) {
  AsyncInvoker invoker;
  // Create and start the thread.
  Thread thread;
  thread.Start();
  // Try calling functor.
  SetExpectedThreadForIntCallback(Thread::Current());
  invoker.AsyncInvoke(&thread, FunctorA(),
                      &AsyncInvokeTest::IntCallback,
                      static_cast<AsyncInvokeTest*>(this));
  EXPECT_EQ_WAIT(42, int_value_, kWaitTimeout);
}

TEST_F(AsyncInvokeTest, DISABLED_CancelInvoker) {
  // Create and start the thread.
  Thread thread;
  thread.Start();
  // Try destroying invoker during call.
  {
    AsyncInvoker invoker;
    invoker.AsyncInvoke(&thread, FunctorC(),
                        &AsyncInvokeTest::IntCallback,
                        static_cast<AsyncInvokeTest*>(this));
  }
  // With invoker gone, callback should be cancelled.
  Thread::Current()->ProcessMessages(kWaitTimeout);
  EXPECT_EQ(0, int_value_);
}

TEST_F(AsyncInvokeTest, CancelCallingThread) {
  AsyncInvoker invoker;
  { // Create and start the thread.
    Thread thread;
    thread.Start();
    // Try calling functor.
    thread.Invoke<void>(Bind(&AsyncInvokeTest::AsyncInvokeIntCallback,
                             static_cast<AsyncInvokeTest*>(this),
                             &invoker, Thread::Current()));
    // Wait for the call to begin.
    ASSERT_TRUE(invoke_started_.Wait(kWaitTimeout));
  }
  // Calling thread is gone. Return message shouldn't happen.
  Thread::Current()->ProcessMessages(kWaitTimeout);
  EXPECT_EQ(0, int_value_);
}

TEST_F(AsyncInvokeTest, KillInvokerBeforeExecute) {
  Thread thread;
  thread.Start();
  {
    AsyncInvoker invoker;
    // Try calling functor.
    thread.Invoke<void>(Bind(&AsyncInvokeTest::AsyncInvokeIntCallback,
                             static_cast<AsyncInvokeTest*>(this),
                             &invoker, Thread::Current()));
    // Wait for the call to begin.
    ASSERT_TRUE(invoke_started_.Wait(kWaitTimeout));
  }
  // Invoker is destroyed. Function should not execute.
  Thread::Current()->ProcessMessages(kWaitTimeout);
  EXPECT_EQ(0, int_value_);
}

TEST_F(AsyncInvokeTest, Flush) {
  AsyncInvoker invoker;
  bool flag1 = false;
  bool flag2 = false;
  // Queue two async calls to the current thread.
  invoker.AsyncInvoke<void>(Thread::Current(),
                            FunctorB(&flag1));
  invoker.AsyncInvoke<void>(Thread::Current(),
                            FunctorB(&flag2));
  // Because we haven't pumped messages, these should not have run yet.
  EXPECT_FALSE(flag1);
  EXPECT_FALSE(flag2);
  // Force them to run now.
  invoker.Flush(Thread::Current());
  EXPECT_TRUE(flag1);
  EXPECT_TRUE(flag2);
}

TEST_F(AsyncInvokeTest, FlushWithIds) {
  AsyncInvoker invoker;
  bool flag1 = false;
  bool flag2 = false;
  // Queue two async calls to the current thread, one with a message id.
  invoker.AsyncInvoke<void>(Thread::Current(),
                            FunctorB(&flag1),
                            5);
  invoker.AsyncInvoke<void>(Thread::Current(),
                            FunctorB(&flag2));
  // Because we haven't pumped messages, these should not have run yet.
  EXPECT_FALSE(flag1);
  EXPECT_FALSE(flag2);
  // Execute pending calls with id == 5.
  invoker.Flush(Thread::Current(), 5);
  EXPECT_TRUE(flag1);
  EXPECT_FALSE(flag2);
  flag1 = false;
  // Execute all pending calls. The id == 5 call should not execute again.
  invoker.Flush(Thread::Current());
  EXPECT_FALSE(flag1);
  EXPECT_TRUE(flag2);
}

#ifdef WIN32
class ComThreadTest : public testing::Test, public MessageHandler {
 public:
  ComThreadTest() : done_(false) {}
 protected:
  virtual void OnMessage(Message* message) {
    HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
    // S_FALSE means the thread was already inited for a multithread apartment.
    EXPECT_EQ(S_FALSE, hr);
    if (SUCCEEDED(hr)) {
      CoUninitialize();
    }
    done_ = true;
  }
  bool done_;
};

TEST_F(ComThreadTest, ComInited) {
  Thread* thread = new ComThread();
  EXPECT_TRUE(thread->Start());
  thread->Post(this, 0);
  EXPECT_TRUE_WAIT(done_, 1000);
  delete thread;
}
#endif
<|endoftext|>