<commit_before>/*
 * Copyright 2016 ScyllaDB
 */

/*
 * This file is part of Scylla.
 *
 * Scylla 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.
 *
 * Scylla 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Scylla.  If not, see <http://www.gnu.org/licenses/>.
 */

class counter_id final {
    utils::UUID to_uuid();
};

class counter_shard final {
    counter_id id();
    int64_t value();
    int64_t logical_clock();
};

class counter_cell_full final stub [[writable]] {
    std::vector<counter_shard> shards;
};

class counter_cell_update final stub [[writable]] {
    int64_t delta;
};

class counter_cell stub [[writable]] {
    api::timestamp_type created_at;
    boost::variant<counter_cell_full, counter_cell_update> value;
};

class tombstone [[writable]] {
    api::timestamp_type timestamp;
    gc_clock::time_point deletion_time;
};

class live_cell stub [[writable]] {
    api::timestamp_type created_at;
    bytes value;
};

class expiring_cell stub [[writable]] {
    gc_clock::duration ttl;
    gc_clock::time_point expiry;
    live_cell c;
};

class dead_cell final stub [[writable]] {
    tombstone tomb;
};

class collection_element stub [[writable]] {
    // key's format depends on its CQL type as defined in the schema and is specified in CQL binary protocol.
    bytes key;
    boost::variant<live_cell, expiring_cell, dead_cell> value;
};

class collection_cell stub [[writable]] {
    tombstone tomb;
    std::vector<collection_element> elements; // sorted by key
};

class column stub [[writable]] {
    uint32_t id;
    boost::variant<boost::variant<live_cell, expiring_cell, dead_cell, counter_cell>, collection_cell> c;
};

class row stub [[writable]] {
    std::vector<column> columns; // sorted by id
};

class no_marker final stub [[writable]] {};

class live_marker stub [[writable]] {
    api::timestamp_type created_at;
};

class expiring_marker stub [[writable]] {
    live_marker lm;
    gc_clock::duration ttl;
    gc_clock::time_point expiry;
};

class dead_marker final stub [[writable]] {
    tombstone tomb;
};

class deletable_row stub [[writable]] {
    clustering_key key;
    boost::variant<live_marker, expiring_marker, dead_marker, no_marker> marker;
    tombstone deleted_at;
    row cells;
    tombstone shadowable_deleted_at [[version 1.8]] = deleted_at;
};

enum class bound_kind : uint8_t {
    excl_end,
    incl_start,
    incl_end,
    excl_start,
};

class range_tombstone [[writable]] {
    clustering_key_prefix start;
    tombstone tomb;
    bound_kind start_kind [[version 1.3]] = bound_kind::incl_start;
    clustering_key_prefix end [[version 1.3]] = start;
    bound_kind end_kind [[version 1.3]] = bound_kind::incl_end;
};

class mutation_partition stub [[writable]] {
    tombstone tomb;
    row static_row;
    std::vector<range_tombstone> range_tombstones; // sorted by key
    std::vector<deletable_row> rows; // sorted by key

};

class mutation stub [[writable]] {
    utils::UUID table_id;
    utils::UUID schema_version;
    partition_key key;
    mutation_partition partition;
};

class column_mapping_entry {
    bytes name();
    sstring type_name();
};

class column_mapping {
    std::vector<column_mapping_entry> columns();
    uint32_t n_static();
};

class canonical_mutation stub [[writable]] {
    utils::UUID table_id;
    utils::UUID schema_version;
    partition_key key;
    column_mapping mapping;
    mutation_partition partition;
}

class clustering_row stub [[writable]] {
    deletable_row row;
};

class static_row stub [[writable]] {
    row cells;
};

class partition_start stub [[writable]] {
    partition_key key;
    tombstone partition_tombstone;
};

class partition_end {
};

class mutation_fragment stub [[writable]] {
    std::variant<clustering_row, static_row, range_tombstone,
                   partition_start, partition_end> fragment;
};

<commit_msg>idl: change the type of mutation_partition_view::rows() to a chunked_vector<commit_after>/*
 * Copyright 2016 ScyllaDB
 */

/*
 * This file is part of Scylla.
 *
 * Scylla 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.
 *
 * Scylla 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Scylla.  If not, see <http://www.gnu.org/licenses/>.
 */

class counter_id final {
    utils::UUID to_uuid();
};

class counter_shard final {
    counter_id id();
    int64_t value();
    int64_t logical_clock();
};

class counter_cell_full final stub [[writable]] {
    std::vector<counter_shard> shards;
};

class counter_cell_update final stub [[writable]] {
    int64_t delta;
};

class counter_cell stub [[writable]] {
    api::timestamp_type created_at;
    boost::variant<counter_cell_full, counter_cell_update> value;
};

class tombstone [[writable]] {
    api::timestamp_type timestamp;
    gc_clock::time_point deletion_time;
};

class live_cell stub [[writable]] {
    api::timestamp_type created_at;
    bytes value;
};

class expiring_cell stub [[writable]] {
    gc_clock::duration ttl;
    gc_clock::time_point expiry;
    live_cell c;
};

class dead_cell final stub [[writable]] {
    tombstone tomb;
};

class collection_element stub [[writable]] {
    // key's format depends on its CQL type as defined in the schema and is specified in CQL binary protocol.
    bytes key;
    boost::variant<live_cell, expiring_cell, dead_cell> value;
};

class collection_cell stub [[writable]] {
    tombstone tomb;
    std::vector<collection_element> elements; // sorted by key
};

class column stub [[writable]] {
    uint32_t id;
    boost::variant<boost::variant<live_cell, expiring_cell, dead_cell, counter_cell>, collection_cell> c;
};

class row stub [[writable]] {
    std::vector<column> columns; // sorted by id
};

class no_marker final stub [[writable]] {};

class live_marker stub [[writable]] {
    api::timestamp_type created_at;
};

class expiring_marker stub [[writable]] {
    live_marker lm;
    gc_clock::duration ttl;
    gc_clock::time_point expiry;
};

class dead_marker final stub [[writable]] {
    tombstone tomb;
};

class deletable_row stub [[writable]] {
    clustering_key key;
    boost::variant<live_marker, expiring_marker, dead_marker, no_marker> marker;
    tombstone deleted_at;
    row cells;
    tombstone shadowable_deleted_at [[version 1.8]] = deleted_at;
};

enum class bound_kind : uint8_t {
    excl_end,
    incl_start,
    incl_end,
    excl_start,
};

class range_tombstone [[writable]] {
    clustering_key_prefix start;
    tombstone tomb;
    bound_kind start_kind [[version 1.3]] = bound_kind::incl_start;
    clustering_key_prefix end [[version 1.3]] = start;
    bound_kind end_kind [[version 1.3]] = bound_kind::incl_end;
};

class mutation_partition stub [[writable]] {
    tombstone tomb;
    row static_row;
    std::vector<range_tombstone> range_tombstones; // sorted by key
    utils::chunked_vector<deletable_row> rows; // sorted by key

};

class mutation stub [[writable]] {
    utils::UUID table_id;
    utils::UUID schema_version;
    partition_key key;
    mutation_partition partition;
};

class column_mapping_entry {
    bytes name();
    sstring type_name();
};

class column_mapping {
    std::vector<column_mapping_entry> columns();
    uint32_t n_static();
};

class canonical_mutation stub [[writable]] {
    utils::UUID table_id;
    utils::UUID schema_version;
    partition_key key;
    column_mapping mapping;
    mutation_partition partition;
}

class clustering_row stub [[writable]] {
    deletable_row row;
};

class static_row stub [[writable]] {
    row cells;
};

class partition_start stub [[writable]] {
    partition_key key;
    tombstone partition_tombstone;
};

class partition_end {
};

class mutation_fragment stub [[writable]] {
    std::variant<clustering_row, static_row, range_tombstone,
                   partition_start, partition_end> fragment;
};

<|endoftext|>


<commit_before>//===-- WriteConst.cpp - Functions for writing constants ---------*- C++ -*--=//
//
// This file implements the routines for encoding constants to a bytecode
// stream.
//
// Note that the performance of this library is not terribly important, because
// it shouldn't be used by JIT type applications... so it is not a huge focus
// at least.  :)
//
//===----------------------------------------------------------------------===//

#include "WriterInternals.h"
#include "llvm/ConstPoolVals.h"
#include "llvm/SymbolTable.h"
#include "llvm/DerivedTypes.h"

void BytecodeWriter::outputType(const Type *T) {
  output_vbr((unsigned)T->getPrimitiveID(), Out);

  // That's all there is to handling primitive types...
  if (T->isPrimitiveType())
    return;     // We might do this if we alias a prim type: %x = type int

  switch (T->getPrimitiveID()) {   // Handle derived types now.
  case Type::MethodTyID: {
    const MethodType *MT = (const MethodType*)T;
    int Slot = Table.getValSlot(MT->getReturnType());
    assert(Slot != -1 && "Type used but not available!!");
    output_vbr((unsigned)Slot, Out);

    // Output all of the arguments...
    MethodType::ParamTypes::const_iterator I = MT->getParamTypes().begin();
    for (; I != MT->getParamTypes().end(); ++I) {
      Slot = Table.getValSlot(*I);
      assert(Slot != -1 && "Type used but not available!!");
      output_vbr((unsigned)Slot, Out);
    }

    // Terminate list with VoidTy
    output_vbr((unsigned)Type::VoidTy->getPrimitiveID(), Out);
    break;
  }

  case Type::ArrayTyID: {
    const ArrayType *AT = (const ArrayType*)T;
    int Slot = Table.getValSlot(AT->getElementType());
    assert(Slot != -1 && "Type used but not available!!");
    output_vbr((unsigned)Slot, Out);
    //cerr << "Type slot = " << Slot << " Type = " << T->getName() << endl;

    output_vbr(AT->getNumElements(), Out);
    break;
  }

  case Type::StructTyID: {
    const StructType *ST = (const StructType*)T;

    // Output all of the element types...
    StructType::ElementTypes::const_iterator I = ST->getElementTypes().begin();
    for (; I != ST->getElementTypes().end(); ++I) {
      int Slot = Table.getValSlot(*I);
      assert(Slot != -1 && "Type used but not available!!");
      output_vbr((unsigned)Slot, Out);
    }

    // Terminate list with VoidTy
    output_vbr((unsigned)Type::VoidTy->getPrimitiveID(), Out);
    break;
  }

  case Type::PointerTyID: {
    const PointerType *PT = (const PointerType*)T;
    int Slot = Table.getValSlot(PT->getValueType());
    assert(Slot != -1 && "Type used but not available!!");
    output_vbr((unsigned)Slot, Out);
    break;
  }

  case Type::ModuleTyID:
  case Type::PackedTyID:
  default:
    cerr << __FILE__ << ":" << __LINE__ << ": Don't know how to serialize"
	 << " Type '" << T->getName() << "'\n";
    break;
  }
}

bool BytecodeWriter::outputConstant(const ConstPoolVal *CPV) {
  switch (CPV->getType()->getPrimitiveID()) {
  case Type::BoolTyID:    // Boolean Types
    if (((const ConstPoolBool*)CPV)->getValue())
      output_vbr((unsigned)1, Out);
    else
      output_vbr((unsigned)0, Out);
    break;

  case Type::UByteTyID:   // Unsigned integer types...
  case Type::UShortTyID:
  case Type::UIntTyID:
  case Type::ULongTyID:
    output_vbr(((const ConstPoolUInt*)CPV)->getValue(), Out);
    break;

  case Type::SByteTyID:   // Signed integer types...
  case Type::ShortTyID:
  case Type::IntTyID:
  case Type::LongTyID:
    output_vbr(((const ConstPoolSInt*)CPV)->getValue(), Out);
    break;

  case Type::TypeTyID:     // Serialize type type
    outputType(((const ConstPoolType*)CPV)->getValue());
    break;

  case Type::ArrayTyID: {
    const ConstPoolArray *CPA = (const ConstPoolArray *)CPV;
    unsigned size = CPA->getValues().size();
    if (!((const ArrayType *)CPA->getType())->isSized())
      output_vbr(size, Out);            // Not for sized arrays!!!

    for (unsigned i = 0; i < size; i++) {
      int Slot = Table.getValSlot(CPA->getValues()[i]);
      assert(Slot != -1 && "Constant used but not available!!");
      output_vbr((unsigned)Slot, Out);
    }
    break;
  }

  case Type::StructTyID: {
    const ConstPoolStruct *CPS = (const ConstPoolStruct*)CPV;
    const vector<Use> &Vals = CPS->getValues();

    for (unsigned i = 0; i < Vals.size(); ++i) {
      int Slot = Table.getValSlot(Vals[i]);
      assert(Slot != -1 && "Constant used but not available!!");
      output_vbr((unsigned)Slot, Out);
    }
    break;
  }

  case Type::FloatTyID:    // Floating point types...
  case Type::DoubleTyID:
    // TODO: Floating point type serialization

  case Type::VoidTyID:
  case Type::LabelTyID:
  default:
    cerr << __FILE__ << ":" << __LINE__ << ": Don't know how to serialize"
	 << " type '" << CPV->getType()->getName() << "'\n";
    break;
  }
  return false;
}
<commit_msg>Add support to the bytecode writer to recognize floating point constants<commit_after>//===-- WriteConst.cpp - Functions for writing constants ---------*- C++ -*--=//
//
// This file implements the routines for encoding constants to a bytecode
// stream.
//
// Note that the performance of this library is not terribly important, because
// it shouldn't be used by JIT type applications... so it is not a huge focus
// at least.  :)
//
//===----------------------------------------------------------------------===//

#include "WriterInternals.h"
#include "llvm/ConstPoolVals.h"
#include "llvm/SymbolTable.h"
#include "llvm/DerivedTypes.h"

void BytecodeWriter::outputType(const Type *T) {
  output_vbr((unsigned)T->getPrimitiveID(), Out);

  // That's all there is to handling primitive types...
  if (T->isPrimitiveType())
    return;     // We might do this if we alias a prim type: %x = type int

  switch (T->getPrimitiveID()) {   // Handle derived types now.
  case Type::MethodTyID: {
    const MethodType *MT = (const MethodType*)T;
    int Slot = Table.getValSlot(MT->getReturnType());
    assert(Slot != -1 && "Type used but not available!!");
    output_vbr((unsigned)Slot, Out);

    // Output all of the arguments...
    MethodType::ParamTypes::const_iterator I = MT->getParamTypes().begin();
    for (; I != MT->getParamTypes().end(); ++I) {
      Slot = Table.getValSlot(*I);
      assert(Slot != -1 && "Type used but not available!!");
      output_vbr((unsigned)Slot, Out);
    }

    // Terminate list with VoidTy
    output_vbr((unsigned)Type::VoidTy->getPrimitiveID(), Out);
    break;
  }

  case Type::ArrayTyID: {
    const ArrayType *AT = (const ArrayType*)T;
    int Slot = Table.getValSlot(AT->getElementType());
    assert(Slot != -1 && "Type used but not available!!");
    output_vbr((unsigned)Slot, Out);
    //cerr << "Type slot = " << Slot << " Type = " << T->getName() << endl;

    output_vbr(AT->getNumElements(), Out);
    break;
  }

  case Type::StructTyID: {
    const StructType *ST = (const StructType*)T;

    // Output all of the element types...
    StructType::ElementTypes::const_iterator I = ST->getElementTypes().begin();
    for (; I != ST->getElementTypes().end(); ++I) {
      int Slot = Table.getValSlot(*I);
      assert(Slot != -1 && "Type used but not available!!");
      output_vbr((unsigned)Slot, Out);
    }

    // Terminate list with VoidTy
    output_vbr((unsigned)Type::VoidTy->getPrimitiveID(), Out);
    break;
  }

  case Type::PointerTyID: {
    const PointerType *PT = (const PointerType*)T;
    int Slot = Table.getValSlot(PT->getValueType());
    assert(Slot != -1 && "Type used but not available!!");
    output_vbr((unsigned)Slot, Out);
    break;
  }

  case Type::ModuleTyID:
  case Type::PackedTyID:
  default:
    cerr << __FILE__ << ":" << __LINE__ << ": Don't know how to serialize"
	 << " Type '" << T->getName() << "'\n";
    break;
  }
}

bool BytecodeWriter::outputConstant(const ConstPoolVal *CPV) {
  switch (CPV->getType()->getPrimitiveID()) {
  case Type::BoolTyID:    // Boolean Types
    if (((const ConstPoolBool*)CPV)->getValue())
      output_vbr((unsigned)1, Out);
    else
      output_vbr((unsigned)0, Out);
    break;

  case Type::UByteTyID:   // Unsigned integer types...
  case Type::UShortTyID:
  case Type::UIntTyID:
  case Type::ULongTyID:
    output_vbr(((const ConstPoolUInt*)CPV)->getValue(), Out);
    break;

  case Type::SByteTyID:   // Signed integer types...
  case Type::ShortTyID:
  case Type::IntTyID:
  case Type::LongTyID:
    output_vbr(((const ConstPoolSInt*)CPV)->getValue(), Out);
    break;

  case Type::TypeTyID:     // Serialize type type
    outputType(((const ConstPoolType*)CPV)->getValue());
    break;

  case Type::ArrayTyID: {
    const ConstPoolArray *CPA = (const ConstPoolArray *)CPV;
    unsigned size = CPA->getValues().size();
    if (!((const ArrayType *)CPA->getType())->isSized())
      output_vbr(size, Out);            // Not for sized arrays!!!

    for (unsigned i = 0; i < size; i++) {
      int Slot = Table.getValSlot(CPA->getValues()[i]);
      assert(Slot != -1 && "Constant used but not available!!");
      output_vbr((unsigned)Slot, Out);
    }
    break;
  }

  case Type::StructTyID: {
    const ConstPoolStruct *CPS = (const ConstPoolStruct*)CPV;
    const vector<Use> &Vals = CPS->getValues();

    for (unsigned i = 0; i < Vals.size(); ++i) {
      int Slot = Table.getValSlot(Vals[i]);
      assert(Slot != -1 && "Constant used but not available!!");
      output_vbr((unsigned)Slot, Out);
    }
    break;
  }

  case Type::FloatTyID: {   // Floating point types...
    float Tmp = (float)((const ConstPoolFP*)CPV)->getValue();
    output_data(&Tmp, &Tmp+1, Out);
    break;
  }
  case Type::DoubleTyID: {
    double Tmp = ((const ConstPoolFP*)CPV)->getValue();
    output_data(&Tmp, &Tmp+1, Out);
    break;
  }

  case Type::VoidTyID:
  case Type::LabelTyID:
  default:
    cerr << __FILE__ << ":" << __LINE__ << ": Don't know how to serialize"
	 << " type '" << CPV->getType()->getName() << "'\n";
    break;
  }
  return false;
}
<|endoftext|>


<commit_before>#ifndef HEADERS_HPP
#define HEADERS_HPP

#include <array>
#include <cstdint>
#include <cstring>
#include <sstream>
#include <string>

#include <arpa/inet.h>

namespace Headers {

/*! Representation of the etherner header.
 */
struct Ethernet {
	std::array<uint8_t, 6> destMac; //!< Destination MAC
	std::array<uint8_t, 6> srcMac;  //!< Source MAC
	uint16_t ethertype;				//!< Ethertype

	/*! Get the SDU
	 */
	void *getPayload() {
		return reinterpret_cast<void *>(
			reinterpret_cast<uint8_t *>(this) + sizeof(struct Ethernet));
	}

	static std::string addrToStr(std::array<uint8_t, 6> addr) {
		std::stringstream str;
		str << std::hex << static_cast<int>(addr[0]) << ":" << std::hex
			<< static_cast<int>(addr[1]) << ":" << std::hex << static_cast<int>(addr[2])
			<< ":" << std::hex << static_cast<int>(addr[3]) << ":" << std::hex
			<< static_cast<int>(addr[4]) << ":" << std::hex << static_cast<int>(addr[5]);
		return str.str();
	}

	std::string getSrcAddr() { return addrToStr(this->srcMac); }

	std::string getDstAddr() { return addrToStr(this->destMac); }

	uint16_t getEthertype() { return ntohs(this->ethertype); }

	void setSrcAddr(const std::array<uint8_t, 6> addr) {
		memcpy(this->srcMac.data(), addr.data(), 6);
	}

	void setDstAddr(std::array<uint8_t, 6> addr) {
		memcpy(this->destMac.data(), addr.data(), 6);
	}

	void setEthertype(uint16_t type) { this->ethertype = htons(type); }
} __attribute__((packed));

/*! Representation of the IPv4 header.
 */
struct IPv4 {
	uint8_t version_ihl; //!< Version and IHL

	uint8_t version() const { return (version_ihl & 0xf0) >> 4; }
	uint8_t ihl() const { return version_ihl & 0x0f; }

	/*! Set the version field to 4
	 */
	void setVersion() {
		version_ihl &= 0x0f;
		version_ihl |= 0x40;
	}

	/*! Sets the IP header length
	 * \param len length as it will appear in the header
	 */
	void setIHL(uint8_t len) {
		version_ihl &= 0xf0;
		len &= 0x0f;
		version_ihl |= len;
	}

	uint8_t tos;		   //!< Type of Service
	uint16_t total_length; //!< L3-PDU length

	/*! Set the length of the L3-SDU
	 * \param Length of the L3-SDU (IP payload length)
	 */
	void setPayloadLength(uint16_t len) { total_length = htons(ihl() * 4 + len); }

	/*! Get the length of the L3-SDU
	 * \return The length of the payload (host byte order)
	 */
	uint16_t getPayloadLength() const { return ntohl(total_length) - ihl() * 4; }

	uint16_t id;				  //!< Identification
	uint16_t flags_fragmentation; //!< flags and fragmentation offset

	uint16_t fragmentation() const { return flags_fragmentation & 0x1fff; }
	uint16_t flags() const { return flags_fragmentation >> 18; }

	uint8_t ttl;   //!< Time to live
	uint8_t proto; //!< next protocol

	static constexpr uint8_t PROTO_ICMP = 1;
	static constexpr uint8_t PROTO_TCP = 6;
	static constexpr uint8_t PROTO_UDP = 17;

	void setProtoICMP() { proto = PROTO_ICMP; }

	void setProtoTCP() { proto = PROTO_TCP; }

	void setProtoUDP() { proto = PROTO_UDP; }

	uint16_t checksum; //!< header checksum
	uint32_t srcIP;	//!< source IPv4 address
	uint32_t dstIP;	//!< destination IPv4 address

	/*! Set the source ip
	 * \param ip Source IP in host byte order
	 */
	void setSrcIP(uint32_t ip) { srcIP = htonl(ip); }

	/*! Set the destination ip
	 * \param ip Destination IP in host byte order
	 */
	void setDstIP(uint32_t ip) { dstIP = htonl(ip); }

	/*! Get the source IP
	 * \return Source IP in host byte order
	 */
	uint32_t getSrcIP() const { return ntohl(srcIP); }

	/*! Get the destination IP
	 * \return Destination IP in host byte order
	 */
	uint32_t getDstIP() const { return ntohl(dstIP); }

	/*! Get the SDU
	 */
	void *getPayload() {
		return reinterpret_cast<void *>(reinterpret_cast<uint8_t *>(this) + 4 * ihl());
	}

	static std::string addrToStr(uint32_t addr) {
		std::stringstream str;
		str << (addr >> 24) << "." << ((addr >> 16) & 0xff) << "." << ((addr >> 8) & 0xff)
			<< "." << (addr & 0xff);
		return str.str();
	}

	std::string getSrcAddr() { return addrToStr(this->srcIP); }

	std::string getDstAddr() { return addrToStr(this->dstIP); }

	void setLength(uint16_t len) { this->total_length = htons(len); }

	uint16_t getLength() { return ntohs(this->total_length); }

	/*! Fill out the header checksum for this packet
	 */
	void calcChecksum() {
		uint32_t result = 0;
		uint16_t *hdr_cast = reinterpret_cast<uint16_t *>(this);

		this->checksum = 0;
		for (uint8_t i = 0; i < (this->ihl() * 4); i++) {
			result += ntohs(hdr_cast[i]);
			if (result & (1 << 16)) {
				result &= 0xffff;
				result++;
			}
		}

		this->checksum = htons(~result);
	};

} __attribute__((packed));

/*! Representation of the TCP header.
 */
struct Tcp {
	uint16_t srcPort;	  //!< Source port
	uint16_t dstPort;	  //!< Destination port
	uint32_t seq;		   //!< Sequence number
	uint32_t ack;		   //!< Acknowledgement number
	uint16_t offset_flags; //!< Data offset and flags
	uint16_t window;	   //!< Receive window
	uint16_t checksum;	 //!< Checksum
	uint16_t urgend_ptr;   //!< Urgent pointer

	/*! Get the SDU
	 */
	void *getPayload() {
		return reinterpret_cast<void *>(
			reinterpret_cast<uint8_t *>(this) + sizeof(struct Tcp));
	}

} __attribute__((packed));

/*! Representation of the UDP header.
 */
struct Udp {
	uint16_t srcPort;  //!< Source port
	uint16_t dstPort;  //!< Destination port
	uint16_t len;	  //!< Length
	uint16_t checksum; //!< Checksum

	/*! Set the source port
	 * \param Source port in host byte order
	 */
	void setSrcPort(uint16_t p) { srcPort = htons(p); }

	/*! Set the destination port
	 * \param Destinatino port in host byte order
	 */
	void setDstPort(uint16_t p) { dstPort = htons(p); }

	/*! Get the source port
	 * \return Source port in host byte order
	 */
	uint16_t getSrcPort() const { return ntohs(srcPort); }

	/*! Get the destination port
	 * \return Destination port in host byte order
	 */
	uint16_t getDstPort() const { return ntohs(dstPort); }

	/*! Get the length of the L4-SDU (UDP payload)
	 * \return Length of the payload (host byte order)
	 */
	uint16_t getPayloadLength() const { return ntohs(len) - sizeof(struct Udp); }

	/*! Set the length of the L4-SDU (UDP payload)
	 * \param Length of the payload (host byte order)
	 */
	void setPayloadLength(uint16_t length) { len = htons(length + sizeof(struct Udp)); }

	/*! Get the SDU
	 */
	void *getPayload() {
		return reinterpret_cast<void *>(
			reinterpret_cast<uint8_t *>(this) + sizeof(struct Udp));
	}

} __attribute__((packed));

/*! Representation of the ICMP header
 */
struct Icmp {
	uint8_t type;	  //!< Type
	uint8_t code;	  //!< Code
	uint16_t checksum; //!< Checksum
} __attribute__((packed));

} // namespace Headers

#endif /* HEADERS_HPP */
<commit_msg>more comments for headers<commit_after>#ifndef HEADERS_HPP
#define HEADERS_HPP

#include <array>
#include <cstdint>
#include <cstring>
#include <sstream>
#include <string>

#include <arpa/inet.h>

namespace Headers {

/*! Representation of the etherner header. */
struct Ethernet {
	std::array<uint8_t, 6> destMac; //!< Destination MAC
	std::array<uint8_t, 6> srcMac;  //!< Source MAC
	uint16_t ethertype;				//!< Ethertype

	/*! Get the SDU
	 * \return Pointer to the payload
	 */
	void *getPayload() {
		return reinterpret_cast<void *>(
			reinterpret_cast<uint8_t *>(this) + sizeof(struct Ethernet));
	}

	static std::string addrToStr(std::array<uint8_t, 6> addr) {
		std::stringstream str;
		str << std::hex << static_cast<int>(addr[0]) << ":" << std::hex
			<< static_cast<int>(addr[1]) << ":" << std::hex << static_cast<int>(addr[2])
			<< ":" << std::hex << static_cast<int>(addr[3]) << ":" << std::hex
			<< static_cast<int>(addr[4]) << ":" << std::hex << static_cast<int>(addr[5]);
		return str.str();
	}

	std::string getSrcAddr() { return addrToStr(this->srcMac); }

	std::string getDstAddr() { return addrToStr(this->destMac); }

	/*! Get the ethertype
	 * \return Ethertype in host byte order
	 */
	uint16_t getEthertype() { return ntohs(this->ethertype); }

	/*! Set the ethertype
	 * \param type Ethertype in host byte order
	 */
	void setEthertype(uint16_t type) { this->ethertype = htons(type); }

	void setSrcAddr(const std::array<uint8_t, 6> addr) {
		memcpy(this->srcMac.data(), addr.data(), 6);
	}

	void setDstAddr(std::array<uint8_t, 6> addr) {
		memcpy(this->destMac.data(), addr.data(), 6);
	}

} __attribute__((packed));

/*! Representation of the IPv4 header. */
struct IPv4 {
	uint8_t version_ihl; //!< Version and IHL

	uint8_t version() const { return (version_ihl & 0xf0) >> 4; }
	uint8_t ihl() const { return version_ihl & 0x0f; }

	/*! Set the version field to 4
	 */
	void setVersion() {
		version_ihl &= 0x0f;
		version_ihl |= 0x40;
	}

	/*! Sets the IP header length
	 * \param len length as it will appear in the header
	 */
	void setIHL(uint8_t len) {
		version_ihl &= 0xf0;
		len &= 0x0f;
		version_ihl |= len;
	}

	uint8_t tos;		   //!< Type of Service
	uint16_t total_length; //!< L3-PDU length

	/*! Set the length of the L3-SDU
	 * \param Length of the L3-SDU (IP payload length)
	 */
	void setPayloadLength(uint16_t len) { total_length = htons(ihl() * 4 + len); }

	/*! Get the length of the L3-SDU
	 * \return The length of the payload (host byte order)
	 */
	uint16_t getPayloadLength() const { return ntohl(total_length) - ihl() * 4; }

	uint16_t id;				  //!< Identification
	uint16_t flags_fragmentation; //!< flags and fragmentation offset

	uint16_t fragmentation() const { return flags_fragmentation & 0x1fff; }
	uint16_t flags() const { return flags_fragmentation >> 18; }

	uint8_t ttl;   //!< Time to live
	uint8_t proto; //!< next protocol

	static constexpr uint8_t PROTO_ICMP = 1;
	static constexpr uint8_t PROTO_TCP = 6;
	static constexpr uint8_t PROTO_UDP = 17;

	/*! Set the protocol to ICMP */
	void setProtoICMP() { proto = PROTO_ICMP; }

	/*! Set the protocol to TCP */
	void setProtoTCP() { proto = PROTO_TCP; }

	/*! Set the protocol to UDP */
	void setProtoUDP() { proto = PROTO_UDP; }

	uint16_t checksum; //!< header checksum
	uint32_t srcIP;	//!< source IPv4 address
	uint32_t dstIP;	//!< destination IPv4 address

	/*! Set the source ip
	 * \param ip Source IP in host byte order
	 */
	void setSrcIP(uint32_t ip) { srcIP = htonl(ip); }

	/*! Set the destination ip
	 * \param ip Destination IP in host byte order
	 */
	void setDstIP(uint32_t ip) { dstIP = htonl(ip); }

	/*! Get the source IP
	 * \return Source IP in host byte order
	 */
	uint32_t getSrcIP() const { return ntohl(srcIP); }

	/*! Get the destination IP
	 * \return Destination IP in host byte order
	 */
	uint32_t getDstIP() const { return ntohl(dstIP); }

	/*! Get the SDU
	 * \return Pointer to the payload
	 */
	void *getPayload() {
		return reinterpret_cast<void *>(reinterpret_cast<uint8_t *>(this) + 4 * ihl());
	}

	static std::string addrToStr(uint32_t addr) {
		std::stringstream str;
		str << (addr >> 24) << "." << ((addr >> 16) & 0xff) << "." << ((addr >> 8) & 0xff)
			<< "." << (addr & 0xff);
		return str.str();
	}

	std::string getSrcAddr() { return addrToStr(this->srcIP); }

	std::string getDstAddr() { return addrToStr(this->dstIP); }

	void setLength(uint16_t len) { this->total_length = htons(len); }

	uint16_t getLength() { return ntohs(this->total_length); }

	/*! Fill out the header checksum for this packet */
	void calcChecksum() {
		uint32_t result = 0;
		uint16_t *hdr_cast = reinterpret_cast<uint16_t *>(this);

		this->checksum = 0;
		for (uint8_t i = 0; i < (this->ihl() * 4); i++) {
			result += ntohs(hdr_cast[i]);
			if (result & (1 << 16)) {
				result &= 0xffff;
				result++;
			}
		}

		this->checksum = htons(~result);
	};

} __attribute__((packed));

/*! Representation of the TCP header. */
struct Tcp {
	uint16_t srcPort;	  //!< Source port
	uint16_t dstPort;	  //!< Destination port
	uint32_t seq;		   //!< Sequence number
	uint32_t ack;		   //!< Acknowledgement number
	uint16_t offset_flags; //!< Data offset and flags
	uint16_t window;	   //!< Receive window
	uint16_t checksum;	 //!< Checksum
	uint16_t urgend_ptr;   //!< Urgent pointer

	/*! Get the SDU
	 * \return Pointer to the payload
	 */
	void *getPayload() {
		return reinterpret_cast<void *>(
			reinterpret_cast<uint8_t *>(this) + sizeof(struct Tcp));
	}

} __attribute__((packed));

/*! Representation of the UDP header. */
struct Udp {
	uint16_t srcPort;  //!< Source port
	uint16_t dstPort;  //!< Destination port
	uint16_t len;	  //!< Length
	uint16_t checksum; //!< Checksum

	/*! Set the source port
	 * \param Source port in host byte order
	 */
	void setSrcPort(uint16_t p) { srcPort = htons(p); }

	/*! Set the destination port
	 * \param Destinatino port in host byte order
	 */
	void setDstPort(uint16_t p) { dstPort = htons(p); }

	/*! Get the source port
	 * \return Source port in host byte order
	 */
	uint16_t getSrcPort() const { return ntohs(srcPort); }

	/*! Get the destination port
	 * \return Destination port in host byte order
	 */
	uint16_t getDstPort() const { return ntohs(dstPort); }

	/*! Get the length of the L4-SDU (UDP payload)
	 * \return Length of the payload (host byte order)
	 */
	uint16_t getPayloadLength() const { return ntohs(len) - sizeof(struct Udp); }

	/*! Set the length of the L4-SDU (UDP payload)
	 * \param Length of the payload (host byte order)
	 */
	void setPayloadLength(uint16_t length) { len = htons(length + sizeof(struct Udp)); }

	/*! Get the SDU
	 * \return Pointer to the payload
	 */
	void *getPayload() {
		return reinterpret_cast<void *>(
			reinterpret_cast<uint8_t *>(this) + sizeof(struct Udp));
	}

} __attribute__((packed));

/*! Representation of the ICMP header */
struct Icmp {
	uint8_t type;	  //!< Type
	uint8_t code;	  //!< Code
	uint16_t checksum; //!< Checksum
} __attribute__((packed));

} // namespace Headers

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


<commit_before>/*
 * Copyright (c) 2014 Samsung Electronics Co., Ltd.
 *
 * 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.
 *
 */

// CLASS HEADER
#include "accessibility-adaptor-impl.h"

// EXTERNAL INCLUDES
#include <vconf.h>

#include <dali/public-api/object/type-registry.h>
#include <dali/integration-api/debug.h>

// INTERNAL INCLUDES
#include <singleton-service-impl.h>
#include <system-settings.h>

namespace Dali
{

namespace Internal
{

namespace Adaptor
{

namespace
{

const char * DALI_VCONFKEY_SETAPPL_ACCESSIBILITY_DBUS_TTS = "db/setting/accessibility/atspi";

bool GetEnabledVConf()
{
  int isEnabled = 0;
  vconf_get_bool( DALI_VCONFKEY_SETAPPL_ACCESSIBILITY_DBUS_TTS, &isEnabled );

  if( isEnabled == 0 )
  {
    vconf_get_bool( VCONFKEY_SETAPPL_ACCESSIBILITY_TTS, &isEnabled );
  }

  return (bool)isEnabled;
}

#if defined(DEBUG_ENABLED)
Debug::Filter* gAccessibilityAdaptorLogFilter = Debug::Filter::New( Debug::NoLogging, false, "LOG_ACCESSIBILITY_ADAPTOR" );
#endif

void AccessibilityOnOffNotification(keynode_t* node, void* data)
{
  AccessibilityAdaptor* adaptor = static_cast<AccessibilityAdaptor*>( data );

  bool isEnabled = GetEnabledVConf();

  DALI_LOG_INFO( gAccessibilityAdaptorLogFilter, Debug::General, "[%s:%d] %s\n", __FUNCTION__, __LINE__, isEnabled ? "ENABLED" : "DISABLED" );

  if( isEnabled )
  {
    adaptor->EnableAccessibility();
  }
  else
  {
    adaptor->DisableAccessibility();
  }
}

} // unnamed namespace

Dali::AccessibilityAdaptor AccessibilityAdaptor::Get()
{
  Dali::AccessibilityAdaptor adaptor;

  Dali::SingletonService service( SingletonService::Get() );
  if ( service )
  {
    // Check whether the singleton is already created
    Dali::BaseHandle handle = service.GetSingleton( typeid( Dali::AccessibilityAdaptor ) );
    if(handle)
    {
      // If so, downcast the handle
      adaptor = Dali::AccessibilityAdaptor( dynamic_cast< AccessibilityAdaptor* >( handle.GetObjectPtr() ) );
    }
    else
    {
      adaptor = Dali::AccessibilityAdaptor( new AccessibilityAdaptor() );
      AccessibilityAdaptor& adaptorImpl = AccessibilityAdaptor::GetImplementation( adaptor );

      bool isEnabled = GetEnabledVConf();

      if( isEnabled )
      {
        adaptorImpl.EnableAccessibility();
      }
      DALI_LOG_INFO( gAccessibilityAdaptorLogFilter, Debug::General, "[%s:%d] %s\n", __FUNCTION__, __LINE__, isEnabled ? "ENABLED" : "DISABLED" );

      vconf_notify_key_changed( DALI_VCONFKEY_SETAPPL_ACCESSIBILITY_DBUS_TTS, AccessibilityOnOffNotification, &adaptorImpl );
      vconf_notify_key_changed( VCONFKEY_SETAPPL_ACCESSIBILITY_TTS, AccessibilityOnOffNotification, &adaptorImpl );

      service.Register( typeid( adaptor ), adaptor );
    }
  }

  return adaptor;
}

void AccessibilityAdaptor::OnDestroy()
{
  vconf_ignore_key_changed( VCONFKEY_SETAPPL_ACCESSIBILITY_TTS, AccessibilityOnOffNotification );
  vconf_ignore_key_changed( DALI_VCONFKEY_SETAPPL_ACCESSIBILITY_DBUS_TTS, AccessibilityOnOffNotification );
}

} // namespace Adaptor

} // namespace Internal

} // namespace Dali
<commit_msg>Fix -Werror=old-style-cast error<commit_after>/*
 * Copyright (c) 2014 Samsung Electronics Co., Ltd.
 *
 * 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.
 *
 */

// CLASS HEADER
#include "accessibility-adaptor-impl.h"

// EXTERNAL INCLUDES
#include <vconf.h>

#include <dali/public-api/object/type-registry.h>
#include <dali/integration-api/debug.h>

// INTERNAL INCLUDES
#include <singleton-service-impl.h>
#include <system-settings.h>

namespace Dali
{

namespace Internal
{

namespace Adaptor
{

namespace
{

const char * DALI_VCONFKEY_SETAPPL_ACCESSIBILITY_DBUS_TTS = "db/setting/accessibility/atspi";

bool GetEnabledVConf()
{
  int isEnabled = 0;
  vconf_get_bool( DALI_VCONFKEY_SETAPPL_ACCESSIBILITY_DBUS_TTS, &isEnabled );

  if( isEnabled == 0 )
  {
    vconf_get_bool( VCONFKEY_SETAPPL_ACCESSIBILITY_TTS, &isEnabled );
  }

  return static_cast<bool>(isEnabled);
}

#if defined(DEBUG_ENABLED)
Debug::Filter* gAccessibilityAdaptorLogFilter = Debug::Filter::New( Debug::NoLogging, false, "LOG_ACCESSIBILITY_ADAPTOR" );
#endif

void AccessibilityOnOffNotification(keynode_t* node, void* data)
{
  AccessibilityAdaptor* adaptor = static_cast<AccessibilityAdaptor*>( data );

  bool isEnabled = GetEnabledVConf();

  DALI_LOG_INFO( gAccessibilityAdaptorLogFilter, Debug::General, "[%s:%d] %s\n", __FUNCTION__, __LINE__, isEnabled ? "ENABLED" : "DISABLED" );

  if( isEnabled )
  {
    adaptor->EnableAccessibility();
  }
  else
  {
    adaptor->DisableAccessibility();
  }
}

} // unnamed namespace

Dali::AccessibilityAdaptor AccessibilityAdaptor::Get()
{
  Dali::AccessibilityAdaptor adaptor;

  Dali::SingletonService service( SingletonService::Get() );
  if ( service )
  {
    // Check whether the singleton is already created
    Dali::BaseHandle handle = service.GetSingleton( typeid( Dali::AccessibilityAdaptor ) );
    if(handle)
    {
      // If so, downcast the handle
      adaptor = Dali::AccessibilityAdaptor( dynamic_cast< AccessibilityAdaptor* >( handle.GetObjectPtr() ) );
    }
    else
    {
      adaptor = Dali::AccessibilityAdaptor( new AccessibilityAdaptor() );
      AccessibilityAdaptor& adaptorImpl = AccessibilityAdaptor::GetImplementation( adaptor );

      bool isEnabled = GetEnabledVConf();

      if( isEnabled )
      {
        adaptorImpl.EnableAccessibility();
      }
      DALI_LOG_INFO( gAccessibilityAdaptorLogFilter, Debug::General, "[%s:%d] %s\n", __FUNCTION__, __LINE__, isEnabled ? "ENABLED" : "DISABLED" );

      vconf_notify_key_changed( DALI_VCONFKEY_SETAPPL_ACCESSIBILITY_DBUS_TTS, AccessibilityOnOffNotification, &adaptorImpl );
      vconf_notify_key_changed( VCONFKEY_SETAPPL_ACCESSIBILITY_TTS, AccessibilityOnOffNotification, &adaptorImpl );

      service.Register( typeid( adaptor ), adaptor );
    }
  }

  return adaptor;
}

void AccessibilityAdaptor::OnDestroy()
{
  vconf_ignore_key_changed( VCONFKEY_SETAPPL_ACCESSIBILITY_TTS, AccessibilityOnOffNotification );
  vconf_ignore_key_changed( DALI_VCONFKEY_SETAPPL_ACCESSIBILITY_DBUS_TTS, AccessibilityOnOffNotification );
}

} // namespace Adaptor

} // namespace Internal

} // namespace Dali
<|endoftext|>


<commit_before>#include"CCThreadPoolItem.h"

namespace nTool
{
	template<class Func_t>
	void CThreadPoolItem<Func_t>::loop_()
	{
		while(waiting_(),!destructor_)
			exec_->exec();
	}

	template<class Func_t>
	CThreadPoolItem<Func_t>::CThreadPoolItem()
		:destructor_{false},joinable_{false},wait_{0},thr_{&CThreadPoolItem<Func_t>::loop_,this}{}

	template<class Func_t>
	template<class Func,class ... Args>
	void CThreadPoolItem<Func_t>::assign(Func &&func,Args &&...args)
	{
		exec_=std::make_unique<CThreadPoolItemExecutorJoin<Func_t>>(commun_.get(),std::forward<Func>(func),std::forward<Args>(args)...);
		joinable_=true;
		wake_();
	}

	template<class Func_t>
	template<class Func,class ... Args>
	void CThreadPoolItem<Func_t>::assign_and_detach(Func &&func,Args &&...args)
	{
		exec_=std::make_unique<CThreadPoolItemExecutorDetach<Func_t>>(commun_.get(),std::forward<Func>(func),std::forward<Args>(args)...);
		joinable_=false;
		wake_();
	}

	template<class Func_t>
	template<class Func,class ... Args>
	void CThreadPoolItem<Func_t>::assign_and_ret(Func &&func,Args &&...args)
	{
		exec_=std::make_unique<CThreadPoolItemExecutorRet<Func_t>>(commun_.get(),std::forward<Func>(func),std::forward<Args>(args)...);
		joinable_=false;
		wake_();
	}

	template<class Func_t>
	CThreadPoolItem<Func_t>::~CThreadPoolItem()
	{
		if(exec_->is_running())
			exec_->wait();
		destructor_=true;
		wake_();
	}

	template<class Func_t>
	IThreadPoolItemExecutorBase<Func_t>::~IThreadPoolItemExecutorBase(){}

	template<class Func_t>
	template<class Func,class ... Args>
	CThreadPoolItemExecutorDetach<Func_t>::CThreadPoolItemExecutorDetach(ThreadPoolCommunBase<Func_t> *commun,Func &&func,Args &&...args)
		:commun_{commun},complete_{0},func_{std::bind(std::forward<Func>(func),std::forward<Args>(args)...)}{}

	template<class Func_t>
	void CThreadPoolItemExecutorDetach<Func_t>::exec()
	{
		func_();
		commun_->communPoolDetach();
		complete_.signal();
	}

	template<class Func_t>
	template<class Func,class ... Args>
	CThreadPoolItemExecutorJoin<Func_t>::CThreadPoolItemExecutorJoin(ThreadPoolCommunBase<Func_t> *commun,Func &&func,Args &&...args)
		:commun_{commun},complete_{0},func_{std::bind(std::forward<Func>(func),std::forward<Args>(args)...)},running_{true}{}

	template<class Func_t>
	void CThreadPoolItemExecutorJoin<Func_t>::exec()
	{
		func_();
		commun_->communPoolFinish();
		complete_.signal();
	}

	template<class Func_t>
	void CThreadPoolItemExecutorJoin<Func_t>::wait()
	{
		complete_.wait();
		running_=false;
		commun_->communPoolJoin();
	}

	template<class Func_t>
	template<class Func,class ... Args>
	CThreadPoolItemExecutorRet<Func_t>::CThreadPoolItemExecutorRet(ThreadPoolCommunBase<Func_t> *commun,Func &&func,Args &&...args)
		:commun_{commun},task_{std::forward<Func>(func),std::forward<Args>(args)...}{}

	template<class Func_t>
	decltype(std::declval<CTask<Func_t>>().get()) CThreadPoolItemExecutorRet<Func_t>::get()
	{
		const auto temp{task_.get()};
		commun_->communPoolDetach();
		return temp;
	}
}<commit_msg>check exec_ is valid<commit_after>#include"CCThreadPoolItem.h"

namespace nTool
{
	template<class Func_t>
	void CThreadPoolItem<Func_t>::loop_()
	{
		while(waiting_(),!destructor_)
			exec_->exec();
	}

	template<class Func_t>
	CThreadPoolItem<Func_t>::CThreadPoolItem()
		:destructor_{false},joinable_{false},wait_{0},thr_{&CThreadPoolItem<Func_t>::loop_,this}{}

	template<class Func_t>
	template<class Func,class ... Args>
	void CThreadPoolItem<Func_t>::assign(Func &&func,Args &&...args)
	{
		exec_=std::make_unique<CThreadPoolItemExecutorJoin<Func_t>>(commun_.get(),std::forward<Func>(func),std::forward<Args>(args)...);
		joinable_=true;
		wake_();
	}

	template<class Func_t>
	template<class Func,class ... Args>
	void CThreadPoolItem<Func_t>::assign_and_detach(Func &&func,Args &&...args)
	{
		exec_=std::make_unique<CThreadPoolItemExecutorDetach<Func_t>>(commun_.get(),std::forward<Func>(func),std::forward<Args>(args)...);
		joinable_=false;
		wake_();
	}

	template<class Func_t>
	template<class Func,class ... Args>
	void CThreadPoolItem<Func_t>::assign_and_ret(Func &&func,Args &&...args)
	{
		exec_=std::make_unique<CThreadPoolItemExecutorRet<Func_t>>(commun_.get(),std::forward<Func>(func),std::forward<Args>(args)...);
		joinable_=false;
		wake_();
	}

	template<class Func_t>
	CThreadPoolItem<Func_t>::~CThreadPoolItem()
	{
		if(exec_&&exec_->is_running())
			exec_->wait();
		destructor_=true;
		wake_();
	}

	template<class Func_t>
	IThreadPoolItemExecutorBase<Func_t>::~IThreadPoolItemExecutorBase(){}

	template<class Func_t>
	template<class Func,class ... Args>
	CThreadPoolItemExecutorDetach<Func_t>::CThreadPoolItemExecutorDetach(ThreadPoolCommunBase<Func_t> *commun,Func &&func,Args &&...args)
		:commun_{commun},complete_{0},func_{std::bind(std::forward<Func>(func),std::forward<Args>(args)...)}{}

	template<class Func_t>
	void CThreadPoolItemExecutorDetach<Func_t>::exec()
	{
		func_();
		commun_->communPoolDetach();
		complete_.signal();
	}

	template<class Func_t>
	template<class Func,class ... Args>
	CThreadPoolItemExecutorJoin<Func_t>::CThreadPoolItemExecutorJoin(ThreadPoolCommunBase<Func_t> *commun,Func &&func,Args &&...args)
		:commun_{commun},complete_{0},func_{std::bind(std::forward<Func>(func),std::forward<Args>(args)...)},running_{true}{}

	template<class Func_t>
	void CThreadPoolItemExecutorJoin<Func_t>::exec()
	{
		func_();
		commun_->communPoolFinish();
		complete_.signal();
	}

	template<class Func_t>
	void CThreadPoolItemExecutorJoin<Func_t>::wait()
	{
		complete_.wait();
		running_=false;
		commun_->communPoolJoin();
	}

	template<class Func_t>
	template<class Func,class ... Args>
	CThreadPoolItemExecutorRet<Func_t>::CThreadPoolItemExecutorRet(ThreadPoolCommunBase<Func_t> *commun,Func &&func,Args &&...args)
		:commun_{commun},task_{std::forward<Func>(func),std::forward<Args>(args)...}{}

	template<class Func_t>
	decltype(std::declval<CTask<Func_t>>().get()) CThreadPoolItemExecutorRet<Func_t>::get()
	{
		const auto temp{task_.get()};
		commun_->communPoolDetach();
		return temp;
	}
}<|endoftext|>


<commit_before>/** \copyright
 * Copyright (c) 2014, Balazs Racz
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are  permitted provided that the following conditions are met:
 *
 *  - Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *
 *  - Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * \file TivaNRZ.hxx
 *
 * Device driver for TivaWare to decode DCC track signal.
 *
 * @author Balazs Racz
 * @date 29 Nov 2014
 */

#include "TivaDCC.hxx"  // for FixedQueue
#include "TivaGPIO.hxx" // for pin definitions
#include "RailcomDriver.hxx" // for debug pins
#include "dcc/Receiver.hxx"

typedef DummyPin PIN_RailcomCutout;

#define SIGNAL_LEVEL_ONE 0x80000000UL

/*
struct DCCDecode
{
    static const auto TIMER_BASE = WTIMER4_BASE;
    static const auto TIMER_PERIPH = SYSCTL_PERIPH_WTIMER4;
    static const auto TIMER_INTERRUPT = INT_WTIMER4A;
    static const auto TIMER = TIMER_A;
    static const auto CFG_CAP_TIME_UP =
        TIMER_CFG_SPLIT_PAIR | TIMER_CFG_A_CAP_TIME_UP | TIMER_CFG_B_ONE_SHOT;
    // Interrupt bits.
    static const auto TIMER_CAP_EVENT = TIMER_CAPA_EVENT;
    static const auto TIMER_TIM_TIMEOUT = TIMER_TIMA_TIMEOUT;

    static const auto OS_INTERRUPT = INT_WTIMER4B;
    DECL_PIN(NRZPIN, D, 4);
    static const auto NRZPIN_CONFIG = GPIO_PD4_WT4CCP0;

    static const uint32_t TIMER_MAX_VALUE = 0x8000000UL;

    static const int Q_SIZE = 16;

};
*/

template <class HW> class TivaDccDecoder : public Node
{
public:
    TivaDccDecoder(const char *name, RailcomDriver *railcom_driver);

    ~TivaDccDecoder()
    {
    }

    /** Handles a raw interrupt. */
    inline void interrupt_handler() __attribute__((always_inline));

    /** Handles a software interrupt to FreeRTOS. */
    inline void os_interrupt_handler() __attribute__((always_inline));

private:
    /** Read from a file or device.
     * @param file file reference for this device
     * @param buf location to place read data
     * @param count number of bytes to read
     * @return number of bytes read upon success, -1 upon failure with errno
     * containing the cause
     */
    ssize_t read(File *file, void *buf, size_t count) OVERRIDE;

    /** Write to a file or device.
     * @param file file reference for this device
     * @param buf location to find write data
     * @param count number of bytes to write
     * @return number of bytes written upon success, -1 upon failure with errno
     * containing the cause
     */
    ssize_t write(File *file, const void *buf, size_t count) OVERRIDE
    {
        return -EINVAL;
    }

    /** Request an ioctl transaction
     * @param file file reference for this device
     * @param node node reference for this device
     * @param key ioctl key
     * @param data key data
     */
    int ioctl(File *file, unsigned long int key, unsigned long data) OVERRIDE;

    void enable();  /**< function to enable device */
    void disable(); /**< function to disable device */

    /** Discards all pending buffers.  Called after disable().
     */
    void flush_buffers()
    {
        while (!inputData_.empty())
        {
            inputData_.increment_front();
        }
    };

    FixedQueue<uint32_t, HW::Q_SIZE> inputData_;
    uint32_t lastTimerValue_;
    uint32_t reloadCount_;
    unsigned lastLevel_;
    bool overflowed_ = false;

    Notifiable *readableNotifiable_ = nullptr;
    RailcomDriver *railcomDriver_; //< notified for cutout events.

    dcc::DccDecoder decoder_;

    DISALLOW_COPY_AND_ASSIGN(TivaDccDecoder);
};

template <class HW>
TivaDccDecoder<HW>::TivaDccDecoder(const char *name,
                                   RailcomDriver *railcom_driver)
    : Node(name)
    , railcomDriver_(railcom_driver)
{
    MAP_SysCtlPeripheralEnable(HW::TIMER_PERIPH);
    MAP_SysCtlPeripheralEnable(HW::NRZPIN_PERIPH);
    MAP_GPIOPinConfigure(HW::NRZPIN_CONFIG);
    MAP_GPIOPinTypeTimer(HW::NRZPIN_BASE, HW::NRZPIN_PIN);

    disable();
}

template <class HW> void TivaDccDecoder<HW>::enable()
{
    disable();
    MAP_TimerClockSourceSet(HW::TIMER_BASE, TIMER_CLOCK_SYSTEM);
    MAP_TimerConfigure(HW::TIMER_BASE, HW::CFG_CAP_TIME_UP);
    MAP_TimerControlStall(HW::TIMER_BASE, HW::TIMER, true);
    MAP_TimerControlEvent(HW::TIMER_BASE, HW::TIMER, TIMER_EVENT_BOTH_EDGES);
    MAP_TimerLoadSet(HW::TIMER_BASE, HW::TIMER, HW::TIMER_MAX_VALUE);
    MAP_TimerPrescaleSet(HW::TIMER_BASE, HW::TIMER, HW::PS_MAX);

    reloadCount_ = 0;
    lastTimerValue_ = 0;

    MAP_TimerIntEnable(HW::TIMER_BASE, HW::TIMER_CAP_EVENT);
    MAP_TimerIntEnable(HW::TIMER_BASE, HW::TIMER_TIM_TIMEOUT);

    MAP_IntPrioritySet(HW::TIMER_INTERRUPT, 0);
    MAP_IntPrioritySet(HW::OS_INTERRUPT, configKERNEL_INTERRUPT_PRIORITY);
    MAP_IntEnable(HW::OS_INTERRUPT);
    MAP_IntEnable(HW::TIMER_INTERRUPT);

    MAP_TimerEnable(HW::TIMER_BASE, HW::TIMER);
}

template <class HW> void TivaDccDecoder<HW>::disable()
{
    MAP_IntDisable(HW::TIMER_INTERRUPT);
    MAP_IntDisable(HW::OS_INTERRUPT);
    MAP_TimerDisable(HW::TIMER_BASE, HW::TIMER);
}

template <class HW>
__attribute__((optimize("-O3"))) void TivaDccDecoder<HW>::interrupt_handler()
{
    // get masked interrupt status
    auto status = MAP_TimerIntStatus(HW::TIMER_BASE, true);
    if (status & HW::TIMER_TIM_TIMEOUT)
    {
        // The timer got reloaded.
        reloadCount_++;
        MAP_TimerIntClear(HW::TIMER_BASE, HW::TIMER_TIM_TIMEOUT);
    }
    // TODO(balazs.racz): Technically it is possible that the timer reload
    // happens between the event match and the interrupt entry. In this case we
    // will incorrectly add a full cycle to the event length.
    if (status & HW::TIMER_CAP_EVENT)
    {
        MAP_TimerIntClear(HW::TIMER_BASE, HW::TIMER_CAP_EVENT);
        static uint32_t raw_new_value;
        raw_new_value = MAP_TimerValueGet(HW::TIMER_BASE, HW::TIMER);
        static uint32_t new_value;
        new_value = raw_new_value;
        while (reloadCount_ > 0)
        {
            new_value += HW::TIMER_MAX_VALUE;
            reloadCount_--;
        }
        // HASSERT(new_value > lastTimerValue_);
        new_value -= lastTimerValue_;
        /*if (!inputData_.full())
        {
            inputData_.back() = overflowed_ ? 3 : new_value;
            overflowed_ = false;
            inputData_.increment_back();
        } else {
            overflowed_ = true;
            }*/
        decoder_.process_data(new_value);
        if (decoder_.state() == dcc::DccDecoder::DCC_MAYBE_CUTOUT)
        {
            railcomDriver_->start_cutout();
        }
        /// TODO(balazs.racz) recognize middle cutout.
        else if (decoder_.state() == dcc::DccDecoder::DCC_PREAMBLE)
        {
            railcomDriver_->end_cutout();
        }
        lastTimerValue_ = raw_new_value;
        MAP_IntPendSet(HW::OS_INTERRUPT);
    }
}

template <class HW>
__attribute__((optimize("-O3"))) void TivaDccDecoder<HW>::os_interrupt_handler()
{
    if (!inputData_.empty())
    {
        Notifiable *n = readableNotifiable_;
        readableNotifiable_ = nullptr;
        if (n)
        {
            n->notify_from_isr();
            os_isr_exit_yield_test(true);
        }
    }
}

template <class HW>
int TivaDccDecoder<HW>::ioctl(File *file, unsigned long int key,
                              unsigned long data)
{
    if (IOC_TYPE(key) == CAN_IOC_MAGIC && IOC_SIZE(key) == NOTIFIABLE_TYPE &&
        key == CAN_IOC_READ_ACTIVE)
    {
        Notifiable *n = reinterpret_cast<Notifiable *>(data);
        HASSERT(n);
        // If there is no data for reading, we put the incoming notification
        // into the holder. Otherwise we notify it immediately.
        if (inputData_.empty())
        {
            portENTER_CRITICAL();
            if (inputData_.empty())
            {
                // We are in a critical section now. If we got into this
                // branch, then the buffer was full at the beginning of the
                // critical section. If the hardware interrupt kicks in now,
                // and sets the os_interrupt to pending, the os interrupt will
                // not happen until we leave the critical section, and thus the
                // swap will be in effect by then.
                swap(n, readableNotifiable_);
            }
            portEXIT_CRITICAL();
        }
        if (n)
        {
            n->notify();
        }
        return 0;
    }
    errno = EINVAL;
    return -1;
}

/** Read from a file or device.
 * @param file file reference for this device
 * @param buf location to place read data
 * @param count number of bytes to read
 * @return number of bytes read upon success, -1 upon failure with errno
 * containing the cause
 */
template <class HW>
ssize_t TivaDccDecoder<HW>::read(File *file, void *buf, size_t count)
{
    if (count != 4)
    {
        return -EINVAL;
    }
    // We only need this critical section to prevent concurrent threads from
    // reading at the same time.
    portENTER_CRITICAL();
    if (inputData_.empty())
    {
        portEXIT_CRITICAL();
        return -EAGAIN;
    }
    uint32_t v = reinterpret_cast<uint32_t>(buf);
    HASSERT((v & 3) == 0); // alignment check.
    uint32_t *pv = static_cast<uint32_t *>(buf);
    *pv = inputData_.front();
    inputData_.increment_front();
    portEXIT_CRITICAL();
    return count;
}
<commit_msg>Adds a debug pin that shows DCC interrupts. Stops triggering unnecessary OS interrupt.<commit_after>/** \copyright
 * Copyright (c) 2014, Balazs Racz
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are  permitted provided that the following conditions are met:
 *
 *  - Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *
 *  - Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * \file TivaNRZ.hxx
 *
 * Device driver for TivaWare to decode DCC track signal.
 *
 * @author Balazs Racz
 * @date 29 Nov 2014
 */

#include "TivaDCC.hxx"  // for FixedQueue
#include "TivaGPIO.hxx" // for pin definitions
#include "RailcomDriver.hxx" // for debug pins
#include "dcc/Receiver.hxx"

typedef DummyPin PIN_RailcomCutout;

#define SIGNAL_LEVEL_ONE 0x80000000UL

/*
struct DCCDecode
{
    static const auto TIMER_BASE = WTIMER4_BASE;
    static const auto TIMER_PERIPH = SYSCTL_PERIPH_WTIMER4;
    static const auto TIMER_INTERRUPT = INT_WTIMER4A;
    static const auto TIMER = TIMER_A;
    static const auto CFG_CAP_TIME_UP =
        TIMER_CFG_SPLIT_PAIR | TIMER_CFG_A_CAP_TIME_UP | TIMER_CFG_B_ONE_SHOT;
    // Interrupt bits.
    static const auto TIMER_CAP_EVENT = TIMER_CAPA_EVENT;
    static const auto TIMER_TIM_TIMEOUT = TIMER_TIMA_TIMEOUT;

    static const auto OS_INTERRUPT = INT_WTIMER4B;
    DECL_PIN(NRZPIN, D, 4);
    static const auto NRZPIN_CONFIG = GPIO_PD4_WT4CCP0;

    static const uint32_t TIMER_MAX_VALUE = 0x8000000UL;

    static const int Q_SIZE = 16;

};
*/

template <class HW> class TivaDccDecoder : public Node
{
public:
    TivaDccDecoder(const char *name, RailcomDriver *railcom_driver);

    ~TivaDccDecoder()
    {
    }

    /** Handles a raw interrupt. */
    inline void interrupt_handler() __attribute__((always_inline));

    /** Handles a software interrupt to FreeRTOS. */
    inline void os_interrupt_handler() __attribute__((always_inline));

private:
    /** Read from a file or device.
     * @param file file reference for this device
     * @param buf location to place read data
     * @param count number of bytes to read
     * @return number of bytes read upon success, -1 upon failure with errno
     * containing the cause
     */
    ssize_t read(File *file, void *buf, size_t count) OVERRIDE;

    /** Write to a file or device.
     * @param file file reference for this device
     * @param buf location to find write data
     * @param count number of bytes to write
     * @return number of bytes written upon success, -1 upon failure with errno
     * containing the cause
     */
    ssize_t write(File *file, const void *buf, size_t count) OVERRIDE
    {
        return -EINVAL;
    }

    /** Request an ioctl transaction
     * @param file file reference for this device
     * @param node node reference for this device
     * @param key ioctl key
     * @param data key data
     */
    int ioctl(File *file, unsigned long int key, unsigned long data) OVERRIDE;

    void enable();  /**< function to enable device */
    void disable(); /**< function to disable device */

    /** Discards all pending buffers.  Called after disable().
     */
    void flush_buffers()
    {
        while (!inputData_.empty())
        {
            inputData_.increment_front();
        }
    };

    FixedQueue<uint32_t, HW::Q_SIZE> inputData_;
    uint32_t lastTimerValue_;
    uint32_t reloadCount_;
    unsigned lastLevel_;
    bool overflowed_ = false;

    Notifiable *readableNotifiable_ = nullptr;
    RailcomDriver *railcomDriver_; //< notified for cutout events.

    dcc::DccDecoder decoder_;

    DISALLOW_COPY_AND_ASSIGN(TivaDccDecoder);
};

template <class HW>
TivaDccDecoder<HW>::TivaDccDecoder(const char *name,
                                   RailcomDriver *railcom_driver)
    : Node(name)
    , railcomDriver_(railcom_driver)
{
    MAP_SysCtlPeripheralEnable(HW::TIMER_PERIPH);
    MAP_SysCtlPeripheralEnable(HW::NRZPIN_PERIPH);
    MAP_GPIOPinConfigure(HW::NRZPIN_CONFIG);
    MAP_GPIOPinTypeTimer(HW::NRZPIN_BASE, HW::NRZPIN_PIN);

    disable();
}

template <class HW> void TivaDccDecoder<HW>::enable()
{
    disable();
    MAP_TimerClockSourceSet(HW::TIMER_BASE, TIMER_CLOCK_SYSTEM);
    MAP_TimerConfigure(HW::TIMER_BASE, HW::CFG_CAP_TIME_UP);
    MAP_TimerControlStall(HW::TIMER_BASE, HW::TIMER, true);
    MAP_TimerControlEvent(HW::TIMER_BASE, HW::TIMER, TIMER_EVENT_BOTH_EDGES);
    MAP_TimerLoadSet(HW::TIMER_BASE, HW::TIMER, HW::TIMER_MAX_VALUE);
    MAP_TimerPrescaleSet(HW::TIMER_BASE, HW::TIMER, HW::PS_MAX);

    reloadCount_ = 0;
    lastTimerValue_ = 0;

    MAP_TimerIntEnable(HW::TIMER_BASE, HW::TIMER_CAP_EVENT);
    MAP_TimerIntEnable(HW::TIMER_BASE, HW::TIMER_TIM_TIMEOUT);

    MAP_IntPrioritySet(HW::TIMER_INTERRUPT, 0);
    MAP_IntPrioritySet(HW::OS_INTERRUPT, configKERNEL_INTERRUPT_PRIORITY);
    MAP_IntEnable(HW::OS_INTERRUPT);
    MAP_IntEnable(HW::TIMER_INTERRUPT);

    MAP_TimerEnable(HW::TIMER_BASE, HW::TIMER);
}

template <class HW> void TivaDccDecoder<HW>::disable()
{
    MAP_IntDisable(HW::TIMER_INTERRUPT);
    MAP_IntDisable(HW::OS_INTERRUPT);
    MAP_TimerDisable(HW::TIMER_BASE, HW::TIMER);
}

template <class HW>
__attribute__((optimize("-O3"))) void TivaDccDecoder<HW>::interrupt_handler()
{
    // get masked interrupt status
    auto status = MAP_TimerIntStatus(HW::TIMER_BASE, true);
    if (status & HW::TIMER_TIM_TIMEOUT)
    {
        // The timer got reloaded.
        reloadCount_++;
        MAP_TimerIntClear(HW::TIMER_BASE, HW::TIMER_TIM_TIMEOUT);
    }
    // TODO(balazs.racz): Technically it is possible that the timer reload
    // happens between the event match and the interrupt entry. In this case we
    // will incorrectly add a full cycle to the event length.
    if (status & HW::TIMER_CAP_EVENT)
    {
        Debug::DccDecodeInterrupts::toggle();

        MAP_TimerIntClear(HW::TIMER_BASE, HW::TIMER_CAP_EVENT);
        static uint32_t raw_new_value;
        raw_new_value = MAP_TimerValueGet(HW::TIMER_BASE, HW::TIMER);
        static uint32_t new_value;
        new_value = raw_new_value;
        while (reloadCount_ > 0)
        {
            new_value += HW::TIMER_MAX_VALUE;
            reloadCount_--;
        }
        // HASSERT(new_value > lastTimerValue_);
        new_value -= lastTimerValue_;
        /*if (!inputData_.full())
        {
            inputData_.back() = overflowed_ ? 3 : new_value;
            overflowed_ = false;
            inputData_.increment_back();
        } else {
            overflowed_ = true;
            }*/
        decoder_.process_data(new_value);
        if (decoder_.state() == dcc::DccDecoder::DCC_MAYBE_CUTOUT)
        {
            railcomDriver_->start_cutout();
        }
        /// TODO(balazs.racz) recognize middle cutout.
        else if (decoder_.state() == dcc::DccDecoder::DCC_PREAMBLE)
        {
            railcomDriver_->end_cutout();
        }
        lastTimerValue_ = raw_new_value;
        // We are not currently writing anything to the inputData_ queue, thus
        // we don't need to send our OS interrupt either. Once we fix to start
        // emitting the actual packets, we need to reenable this interrupt.
        // MAP_IntPendSet(HW::OS_INTERRUPT);
    }
}

template <class HW>
__attribute__((optimize("-O3"))) void TivaDccDecoder<HW>::os_interrupt_handler()
{
    if (!inputData_.empty())
    {
        Notifiable *n = readableNotifiable_;
        readableNotifiable_ = nullptr;
        if (n)
        {
            n->notify_from_isr();
            os_isr_exit_yield_test(true);
        }
    }
}

template <class HW>
int TivaDccDecoder<HW>::ioctl(File *file, unsigned long int key,
                              unsigned long data)
{
    if (IOC_TYPE(key) == CAN_IOC_MAGIC && IOC_SIZE(key) == NOTIFIABLE_TYPE &&
        key == CAN_IOC_READ_ACTIVE)
    {
        Notifiable *n = reinterpret_cast<Notifiable *>(data);
        HASSERT(n);
        // If there is no data for reading, we put the incoming notification
        // into the holder. Otherwise we notify it immediately.
        if (inputData_.empty())
        {
            portENTER_CRITICAL();
            if (inputData_.empty())
            {
                // We are in a critical section now. If we got into this
                // branch, then the buffer was full at the beginning of the
                // critical section. If the hardware interrupt kicks in now,
                // and sets the os_interrupt to pending, the os interrupt will
                // not happen until we leave the critical section, and thus the
                // swap will be in effect by then.
                swap(n, readableNotifiable_);
            }
            portEXIT_CRITICAL();
        }
        if (n)
        {
            n->notify();
        }
        return 0;
    }
    errno = EINVAL;
    return -1;
}

/** Read from a file or device.
 * @param file file reference for this device
 * @param buf location to place read data
 * @param count number of bytes to read
 * @return number of bytes read upon success, -1 upon failure with errno
 * containing the cause
 */
template <class HW>
ssize_t TivaDccDecoder<HW>::read(File *file, void *buf, size_t count)
{
    if (count != 4)
    {
        return -EINVAL;
    }
    // We only need this critical section to prevent concurrent threads from
    // reading at the same time.
    portENTER_CRITICAL();
    if (inputData_.empty())
    {
        portEXIT_CRITICAL();
        return -EAGAIN;
    }
    uint32_t v = reinterpret_cast<uint32_t>(buf);
    HASSERT((v & 3) == 0); // alignment check.
    uint32_t *pv = static_cast<uint32_t *>(buf);
    *pv = inputData_.front();
    inputData_.increment_front();
    portEXIT_CRITICAL();
    return count;
}
<|endoftext|>


<commit_before>#pragma once

#include <unordered_map>
#include <memory>
#include <type_traits>
#include <tuple>

#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wc++98-compat"
#pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
#pragma clang diagnostic ignored "-Wweak-vtables"
#endif  // CLANG

namespace kgr {

template<typename... Types>
struct Dependency {
	using DependenciesTypes = std::tuple<Types...>;
};

using NoDependencies = Dependency<>;

struct Single {
	using ParentTypes = std::tuple<>;
};

template<typename T>
struct Service;

template<typename... Types>
struct Overrides : Single {
	using ParentTypes = std::tuple<Types...>;
};

namespace detail {

enum class enabler {};

template <bool B, typename T>
using enable_if_t = typename std::enable_if<B, T>::type;

template<int ...>
struct seq { };

template<int N, int ...S>
struct seq_gen : seq_gen<N-1, N-1, S...> { };

template<int ...S>
struct seq_gen<0, S...> {
	using type = seq<S...>;
};

class Holder {
public:
	virtual ~Holder() = default;
};

template<typename T>
class InstanceHolder final : public Holder {
public:
	explicit InstanceHolder(std::shared_ptr<T> instance) : _instance{std::move(instance)} {}

	std::shared_ptr<T> getInstance() const {
		return _instance;
	}

private:
	std::shared_ptr<T> _instance;
};

template<typename T, typename... Args>
class CallbackHolder final : public Holder {
public:
	using callback_t = std::function<std::shared_ptr<T>(Args...)>;

	explicit CallbackHolder(callback_t callback) : _callback{std::move(callback)} {}

	std::shared_ptr<T> operator ()(Args... args) {
		return _callback(args...);
	}
private:
	callback_t _callback;
};

template<typename T, typename ...Args>
std::unique_ptr<T> make_unique( Args&& ...args )
{
    return std::unique_ptr<T>( new T( std::forward<Args>(args)... ) );
}

template <typename T> void type_id() {}
using type_id_fn = void(*)();

} // namespace detail

class Container : public std::enable_shared_from_this<Container> {
	template<typename Condition, typename T = detail::enabler> using enable_if = detail::enable_if_t<Condition::value, T>;
	template<typename Condition, typename T = detail::enabler> using disable_if = detail::enable_if_t<!Condition::value, T>;
	template<typename T> using is_service_single = std::is_base_of<Single, Service<T>>;
	template<typename T> using is_abstract = std::is_abstract<T>;
	template<typename T> using is_base_of_container = std::is_base_of<Container, T>;
	template<typename T> using is_container = std::is_same<T, Container>;
	template<typename T> using dependency_types = typename Service<T>::DependenciesTypes;
	template<typename T> using parent_types = typename Service<T>::ParentTypes;
	template <typename Tuple> using tuple_seq = typename detail::seq_gen<std::tuple_size<Tuple>::value>::type;
	template<int S, typename T> using parent_element = typename std::tuple_element<S, parent_types<T>>::type;
	template<int S, typename Tuple> using tuple_element = typename std::tuple_element<S, Tuple>::type;
	using holder_ptr = std::unique_ptr<detail::Holder>;
	using holder_cont = std::unordered_map<detail::type_id_fn, holder_ptr>;
	constexpr static detail::enabler null = {};
public:
	Container() = default;
	Container(const Container &) = default;
	Container(Container &&) = default;
	Container& operator =(const Container &) = default;
	Container& operator =(Container &&) = default;
	virtual ~Container() = default;

	template<typename T>
	void instance(std::shared_ptr<T> service) {
		static_assert(is_service_single<T>::value, "instance only accept Single Service instance.");

		call_save_instance(std::move(service), tuple_seq<parent_types<T>>{});
	}

	template<typename T>
	void instance() {
		static_assert(is_service_single<T>::value, "instance only accept Single Service instance.");

		instance(make_service<T>());
	}

	template<typename T, disable_if<is_abstract<T>> = null, disable_if<is_base_of_container<T>> = null>
	std::shared_ptr<T> service() {
		return get_service<T>();
	}

	template<typename T, enable_if<is_container<T>> = null>
	std::shared_ptr<T> service() {
		return shared_from_this();
	}

	template<typename T, disable_if<is_container<T>> = null, enable_if<is_base_of_container<T>> = null>
	std::shared_ptr<T> service() {
		return std::dynamic_pointer_cast<T>(shared_from_this());
	}

	template<typename T, enable_if<is_abstract<T>> = null>
	std::shared_ptr<T> service() {
		auto it = _services.find(&detail::template type_id<T>);

		if (it != _services.end()) {
			auto holder = static_cast<detail::InstanceHolder<T>*>(it->second.get());

			if (holder) {
				return holder->getInstance();
			}
		}
		return {};
	}

	template<typename T, typename U>
	void callback(U callback) {
		static_assert(!is_service_single<T>::value, "instance does not accept Single Service.");

		save_callback<T, dependency_types<T>>(tuple_seq<dependency_types<T>>{}, callback);
	}

	virtual void init(){}

private:
	template<typename T, enable_if<is_service_single<T>> = null>
	std::shared_ptr<T> get_service() {
		auto it = _services.find(&detail::template type_id<T>);

		if (it == _services.end()) {
			auto service = make_service<T>();
			instance(service);

			return service;
		} else {
			auto holder = static_cast<detail::InstanceHolder<T>*>(it->second.get());

			if (holder) {
				return holder->getInstance();
			}
		}
		return {};
	}

	template<typename T, disable_if<is_service_single<T>> = null>
	std::shared_ptr<T> get_service() {
		return make_service<T>();
	}

	template<typename T, int ...S>
	void call_save_instance(std::shared_ptr<T> service, detail::seq<S...>) {
		save_instance<T, parent_element<S, T>...>(std::move(service));
	}

	template<typename Tuple, int ...S>
	std::tuple<std::shared_ptr<tuple_element<S, Tuple>>...> dependency(detail::seq<S...>) {
		return std::make_tuple(service<tuple_element<S, Tuple>>()...);
	}

	template<typename T, typename Tuple, int ...S>
	std::shared_ptr<T> callback_make_service(detail::seq<S...>, Tuple dependencies) const {
		auto it = _callbacks.find(&detail::template type_id<T>);

		if (it != _callbacks.end()) {
			auto holder = static_cast<detail::CallbackHolder<T, tuple_element<S, Tuple>...>*>(it->second.get());
			if (holder) {
				return (*holder)(std::get<S>(dependencies)...);
			}
		}
		return {};
	}

	template<typename T, typename Tuple, int ...S>
	std::shared_ptr<T> make_service(detail::seq<S...> seq, Tuple dependencies) const {
		auto service = callback_make_service<T, Tuple>(seq, dependencies);

		if (service) {
			return service;
		}

		return std::make_shared<T>(std::get<S>(dependencies)...);
	}

	template <typename T>
	std::shared_ptr<T> make_service() {
		auto seq = tuple_seq<dependency_types<T>>{};
		return make_service<T>(seq, dependency<dependency_types<T>>(seq));
	}

	template<typename T, typename ...Others>
	detail::enable_if_t<(sizeof...(Others) > 0), void> save_instance(std::shared_ptr<T> service) {
		save_instance<T>(service);
		save_instance<Others...>(std::move(service));
	}

	template<typename T>
	void save_instance (std::shared_ptr<T> service) {
		_services[&detail::template type_id<T>] = detail::make_unique<detail::InstanceHolder<T>>(std::move(service));
	}

	template<typename T, typename Tuple, int ...S, typename U>
	void save_callback (detail::seq<S...>, U callback) {
		_callbacks[&detail::template type_id<T>] = detail::make_unique<detail::CallbackHolder<T, std::shared_ptr<tuple_element<S, Tuple>>...>>(callback);
	}

	holder_cont _callbacks;
	holder_cont _services;
};

template<typename T = Container, typename ...Args>
std::shared_ptr<T> make_container(Args&& ...args) {
	static_assert(std::is_base_of<Container, T>::value, "make_container only accept container types.");

	auto container = std::make_shared<T>(std::forward<Args>(args)...);
	container->init();

	return container;
}

}  // namespace kgr

#if defined(__clang__)
#pragma clang diagnostic pop
#endif  // CLANG
<commit_msg>keeping classes as struct (public hinheritance and public members by default)<commit_after>#pragma once

#include <unordered_map>
#include <memory>
#include <type_traits>
#include <tuple>

#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wc++98-compat"
#pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
#pragma clang diagnostic ignored "-Wweak-vtables"
#endif  // CLANG

namespace kgr {

template<typename... Types>
struct Dependency {
	using DependenciesTypes = std::tuple<Types...>;
};

using NoDependencies = Dependency<>;

struct Single {
	using ParentTypes = std::tuple<>;
};

template<typename T>
struct Service;

template<typename... Types>
struct Overrides : Single {
	using ParentTypes = std::tuple<Types...>;
};

namespace detail {

enum class enabler {};

template <bool B, typename T>
using enable_if_t = typename std::enable_if<B, T>::type;

template<int ...>
struct seq { };

template<int N, int ...S>
struct seq_gen : seq_gen<N-1, N-1, S...> { };

template<int ...S>
struct seq_gen<0, S...> {
	using type = seq<S...>;
};

struct Holder {
	virtual ~Holder() = default;
};

template<typename T>
struct InstanceHolder final : Holder {
	explicit InstanceHolder(std::shared_ptr<T> instance) : _instance{std::move(instance)} {}

	std::shared_ptr<T> getInstance() const {
		return _instance;
	}

private:
	std::shared_ptr<T> _instance;
};

template<typename T, typename... Args>
struct CallbackHolder final : Holder {
	using callback_t = std::function<std::shared_ptr<T>(Args...)>;

	explicit CallbackHolder(callback_t callback) : _callback{std::move(callback)} {}

	std::shared_ptr<T> operator ()(Args... args) {
		return _callback(args...);
	}
private:
	callback_t _callback;
};

template<typename T, typename ...Args>
std::unique_ptr<T> make_unique( Args&& ...args )
{
    return std::unique_ptr<T>( new T( std::forward<Args>(args)... ) );
}

template <typename T> void type_id() {}
using type_id_fn = void(*)();

} // namespace detail

struct Container : std::enable_shared_from_this<Container> {
private:
	template<typename Condition, typename T = detail::enabler> using enable_if = detail::enable_if_t<Condition::value, T>;
	template<typename Condition, typename T = detail::enabler> using disable_if = detail::enable_if_t<!Condition::value, T>;
	template<typename T> using is_service_single = std::is_base_of<Single, Service<T>>;
	template<typename T> using is_abstract = std::is_abstract<T>;
	template<typename T> using is_base_of_container = std::is_base_of<Container, T>;
	template<typename T> using is_container = std::is_same<T, Container>;
	template<typename T> using dependency_types = typename Service<T>::DependenciesTypes;
	template<typename T> using parent_types = typename Service<T>::ParentTypes;
	template <typename Tuple> using tuple_seq = typename detail::seq_gen<std::tuple_size<Tuple>::value>::type;
	template<int S, typename T> using parent_element = typename std::tuple_element<S, parent_types<T>>::type;
	template<int S, typename Tuple> using tuple_element = typename std::tuple_element<S, Tuple>::type;
	using holder_ptr = std::unique_ptr<detail::Holder>;
	using holder_cont = std::unordered_map<detail::type_id_fn, holder_ptr>;
	constexpr static detail::enabler null = {};

public:
	Container() = default;
	Container(const Container &) = default;
	Container(Container &&) = default;
	Container& operator =(const Container &) = default;
	Container& operator =(Container &&) = default;
	virtual ~Container() = default;

	template<typename T>
	void instance(std::shared_ptr<T> service) {
		static_assert(is_service_single<T>::value, "instance only accept Single Service instance.");

		call_save_instance(std::move(service), tuple_seq<parent_types<T>>{});
	}

	template<typename T>
	void instance() {
		static_assert(is_service_single<T>::value, "instance only accept Single Service instance.");

		instance(make_service<T>());
	}

	template<typename T, disable_if<is_abstract<T>> = null, disable_if<is_base_of_container<T>> = null>
	std::shared_ptr<T> service() {
		return get_service<T>();
	}

	template<typename T, enable_if<is_container<T>> = null>
	std::shared_ptr<T> service() {
		return shared_from_this();
	}

	template<typename T, disable_if<is_container<T>> = null, enable_if<is_base_of_container<T>> = null>
	std::shared_ptr<T> service() {
		return std::dynamic_pointer_cast<T>(shared_from_this());
	}

	template<typename T, enable_if<is_abstract<T>> = null>
	std::shared_ptr<T> service() {
		auto it = _services.find(&detail::template type_id<T>);

		if (it != _services.end()) {
			auto holder = static_cast<detail::InstanceHolder<T>*>(it->second.get());

			if (holder) {
				return holder->getInstance();
			}
		}
		return {};
	}

	template<typename T, typename U>
	void callback(U callback) {
		static_assert(!is_service_single<T>::value, "instance does not accept Single Service.");

		save_callback<T, dependency_types<T>>(tuple_seq<dependency_types<T>>{}, callback);
	}

	virtual void init(){}

private:
	template<typename T, enable_if<is_service_single<T>> = null>
	std::shared_ptr<T> get_service() {
		auto it = _services.find(&detail::template type_id<T>);

		if (it == _services.end()) {
			auto service = make_service<T>();
			instance(service);

			return service;
		} else {
			auto holder = static_cast<detail::InstanceHolder<T>*>(it->second.get());

			if (holder) {
				return holder->getInstance();
			}
		}
		return {};
	}

	template<typename T, disable_if<is_service_single<T>> = null>
	std::shared_ptr<T> get_service() {
		return make_service<T>();
	}

	template<typename T, int ...S>
	void call_save_instance(std::shared_ptr<T> service, detail::seq<S...>) {
		save_instance<T, parent_element<S, T>...>(std::move(service));
	}

	template<typename Tuple, int ...S>
	std::tuple<std::shared_ptr<tuple_element<S, Tuple>>...> dependency(detail::seq<S...>) {
		return std::make_tuple(service<tuple_element<S, Tuple>>()...);
	}

	template<typename T, typename Tuple, int ...S>
	std::shared_ptr<T> callback_make_service(detail::seq<S...>, Tuple dependencies) const {
		auto it = _callbacks.find(&detail::template type_id<T>);

		if (it != _callbacks.end()) {
			auto holder = static_cast<detail::CallbackHolder<T, tuple_element<S, Tuple>...>*>(it->second.get());
			if (holder) {
				return (*holder)(std::get<S>(dependencies)...);
			}
		}
		return {};
	}

	template<typename T, typename Tuple, int ...S>
	std::shared_ptr<T> make_service(detail::seq<S...> seq, Tuple dependencies) const {
		auto service = callback_make_service<T, Tuple>(seq, dependencies);

		if (service) {
			return service;
		}

		return std::make_shared<T>(std::get<S>(dependencies)...);
	}

	template <typename T>
	std::shared_ptr<T> make_service() {
		auto seq = tuple_seq<dependency_types<T>>{};
		return make_service<T>(seq, dependency<dependency_types<T>>(seq));
	}

	template<typename T, typename ...Others>
	detail::enable_if_t<(sizeof...(Others) > 0), void> save_instance(std::shared_ptr<T> service) {
		save_instance<T>(service);
		save_instance<Others...>(std::move(service));
	}

	template<typename T>
	void save_instance (std::shared_ptr<T> service) {
		_services[&detail::template type_id<T>] = detail::make_unique<detail::InstanceHolder<T>>(std::move(service));
	}

	template<typename T, typename Tuple, int ...S, typename U>
	void save_callback (detail::seq<S...>, U callback) {
		_callbacks[&detail::template type_id<T>] = detail::make_unique<detail::CallbackHolder<T, std::shared_ptr<tuple_element<S, Tuple>>...>>(callback);
	}

	holder_cont _callbacks;
	holder_cont _services;
};

template<typename T = Container, typename ...Args>
std::shared_ptr<T> make_container(Args&& ...args) {
	static_assert(std::is_base_of<Container, T>::value, "make_container only accept container types.");

	auto container = std::make_shared<T>(std::forward<Args>(args)...);
	container->init();

	return container;
}

}  // namespace kgr

#if defined(__clang__)
#pragma clang diagnostic pop
#endif  // CLANG
<|endoftext|>


<commit_before>/*
 * test-query.cc
 *
 *  Created on: 5 sie 2013
 *      Author: loganek
 */

#include <gtest/gtest.h>
#include <gstreamermm.h>

using namespace Gst;
using Glib::RefPtr;

// TODO use std::function instead of c++ pointers - some strange errors occurs
template<typename RetType, typename QType, QueryType type, typename... Args>
void CreatingQueryTest(RefPtr<RetType> (*create_method)(Args...) , Args... args)
{
    RefPtr<Query> query = create_method(args...);

    ASSERT_TRUE(query);

    RefPtr<QType> query_position = RefPtr<QType>::cast_static(query);

    ASSERT_TRUE(query_position);

    ASSERT_EQ(type, query->get_query_type());
}

template<typename QType, QueryType type, typename... Args>
void CreatingQueryTest(Args... args)
{
    CreatingQueryTest<QType, QType, type, Args...>(&QType::create, args...);
}

template<typename QType, QueryType type, typename... Args>
void CreatingQueryTestStatic(RefPtr<Query> (*create_method)(Args...) , Args... args)
{
    CreatingQueryTest<Query, QType, type, Args...>(create_method, args...);
}

TEST(QueryTest, CorrectCreatingQueryBuffering)
{
    CreatingQueryTestStatic<QueryBuffering, QUERY_BUFFERING, Format>(&Query::new_buffering, FORMAT_BUFFERS);
    CreatingQueryTest<QueryBuffering, QUERY_BUFFERING, Format>(FORMAT_BUFFERS);
}

TEST(QueryTest, CorrectCreatingQueryPosition)
{
    CreatingQueryTestStatic<QueryPosition, QUERY_POSITION, Format>(&Query::new_position, FORMAT_PERCENT);
    CreatingQueryTest<QueryPosition, QUERY_POSITION, Format>(FORMAT_PERCENT);
}

TEST(QueryTest, CorrectCreatingQueryConvert)
{
    CreatingQueryTestStatic<QueryConvert, QUERY_CONVERT, Format, gint64, Format>(&Query::new_convert, FORMAT_PERCENT, 10, FORMAT_BYTES);
    CreatingQueryTest<QueryConvert, QUERY_CONVERT, Format, gint64, Format>(FORMAT_PERCENT, 10, FORMAT_BYTES);
}
<commit_msg>replaced bad method names<commit_after>/*
 * test-query.cc
 *
 *  Created on: 5 sie 2013
 *      Author: loganek
 */

#include <gtest/gtest.h>
#include <gstreamermm.h>

using namespace Gst;
using Glib::RefPtr;

// TODO use std::function instead of c++ pointers - some strange errors occurs
template<typename RetType, typename QType, QueryType type, typename... Args>
void CreatingQueryTest(RefPtr<RetType> (*create_method)(Args...) , Args... args)
{
    RefPtr<Query> query = create_method(args...);

    ASSERT_TRUE(query);

    RefPtr<QType> query_position = RefPtr<QType>::cast_static(query);

    ASSERT_TRUE(query_position);

    ASSERT_EQ(type, query->get_query_type());
}

template<typename QType, QueryType type, typename... Args>
void CreatingQueryTest(Args... args)
{
    CreatingQueryTest<QType, QType, type, Args...>(&QType::create, args...);
}

template<typename QType, QueryType type, typename... Args>
void CreatingQueryTestStatic(RefPtr<Query> (*create_method)(Args...) , Args... args)
{
    CreatingQueryTest<Query, QType, type, Args...>(create_method, args...);
}

TEST(QueryTest, CorrectCreatingQueryBuffering)
{
    CreatingQueryTestStatic<QueryBuffering, QUERY_BUFFERING, Format>(&Query::create_buffering, FORMAT_BUFFERS);
    CreatingQueryTest<QueryBuffering, QUERY_BUFFERING, Format>(FORMAT_BUFFERS);
}

TEST(QueryTest, CorrectCreatingQueryPosition)
{
    CreatingQueryTestStatic<QueryPosition, QUERY_POSITION, Format>(&Query::create_position, FORMAT_PERCENT);
    CreatingQueryTest<QueryPosition, QUERY_POSITION, Format>(FORMAT_PERCENT);
}

TEST(QueryTest, CorrectCreatingQueryConvert)
{
    CreatingQueryTestStatic<QueryConvert, QUERY_CONVERT, Format, gint64, Format>(&Query::create_convert, FORMAT_PERCENT, 10, FORMAT_BYTES);
    CreatingQueryTest<QueryConvert, QUERY_CONVERT, Format, gint64, Format>(FORMAT_PERCENT, 10, FORMAT_BYTES);
}
<|endoftext|>