<commit_before>#ifndef OBJECTS_H
#define OBJECTS_H

/*
Defines an Object::ref type, which is a tagged pointer type.
Usage:
	Object::ref x = Object::to_ref(1);//smallint
	Object::ref y = Object::to_ref(new(hp) Generic()); //object
	if(is_a<int>(x)) {
		std::cout << "x = " << as_a<int>(x) << std::endl;
	}
	if(is_a<Generic*>(y)) {
		std::cout << "y.field = " << as_a<Generic*>(y)->field
			<< std::endl;
	}
*/

#include<stdint.h>
#include<climits>

#include"unichars.hpp"

#include"workarounds.hpp"

class Generic;
class Symbol;
class Cons;
class Closure;
class KClosure;

namespace Object {

/*-----------------------------------------------------------------------------
Declare
-----------------------------------------------------------------------------*/
	class ref;
	template<typename T> struct tag_traits;
	/*assume we won't ever need more than 7 bits of tag*/
	typedef unsigned char tag_type;

	template<typename T> static inline ref to_ref(T);
	template<typename T> static inline bool _is_a(ref);
	template<typename T> static inline T _as_a(ref);

	static inline ref t(void);
	static inline bool _is_t(ref);

	static inline ref nil(void);
	static inline bool _is_nil(ref);

	static inline ref from_a_scaled_int(int);
	static inline int to_a_scaled_int(ref);
}

void throw_TypeError(Object::ref, char const*);
void throw_RangeError(char const*);

template<typename T> static inline bool is_a(Object::ref);
template<typename T> static inline T as_a(Object::ref);

static inline bool is_t(Object::ref);

size_t hash_is(Object::ref);

namespace Object {

/*-----------------------------------------------------------------------------
Configuration
-----------------------------------------------------------------------------*/

	static const unsigned char tag_bits = 2;// can bump up to 3 maybe...

	template<> struct tag_traits<int> {
		static const tag_type tag = 0x1;
	};
	template<> struct tag_traits<Generic*> {
		static const tag_type tag = 0x0;
	};
	template<> struct tag_traits<Symbol*> {
		static const tag_type tag = 0x2;
	};
	template<> struct tag_traits<UnicodeChar> {
		static const tag_type tag = 0x3;
	};

/*-----------------------------------------------------------------------------
Provided information
-----------------------------------------------------------------------------*/

	static const tag_type alignment = 1 << tag_bits;
	static const tag_type tag_mask = alignment - 1;

	/*the real range is the smaller of the range of intptr_t
	shifted down by tag bits, or the range of the `int' type
	*/
	static const intptr_t smallint_min =
		(sizeof(int) >= sizeof(intptr_t)) ?
			INTPTR_MIN >> tag_bits :
		/*otherwise*/
			INT_MIN;
	static const intptr_t smallint_max =
		(sizeof(int) >= sizeof(intptr_t)) ?
			INTPTR_MAX >> tag_bits :
		/*otherwise*/
			INT_MAX;

	/*value for "t"*/
	static const intptr_t t_value = ~((intptr_t) tag_mask);

/*-----------------------------------------------------------------------------
The tagged pointer type
-----------------------------------------------------------------------------*/

	/*stefano prefers to use:
		typedef void* ref;
	or maybe:
		typedef intptr_t ref;
	I may change this later on, but for now
	I want to see whether the conceptual
	separation will help and if compilers,
	in general, will be smart enough to
	optimize away the structure.
	*/
	class ref {
	private:
		intptr_t dat;
		ref(intptr_t x) : dat(x) {}
	public:
		ref(void) : dat(0) {}
		inline bool operator==(ref b) {
			return dat == b.dat;
		}
		inline bool operator!=(ref b) {
			return dat != b.dat;
		}
		inline bool operator!(void) {
			return dat == 0;
		}

		/*safe bool idiom*/
		typedef intptr_t (ref::*unspecified_bool_type);
		inline operator unspecified_bool_type(void) const {
			return dat != 0 ? &ref::dat : 0;
		}

		template<typename T> friend ref to_ref(T);
		template<typename T> friend bool _is_a(ref);
		template<typename T> friend T _as_a(ref);

		friend int to_a_scaled_int(ref);
		friend ref from_a_scaled_int(int);

		friend ref t(void);
		friend bool _is_t(ref);
		friend size_t (::hash_is)(Object::ref);
	};

/*-----------------------------------------------------------------------------
Tagged pointer factories
-----------------------------------------------------------------------------*/

	template<typename T>
	static inline ref to_ref(T x) {
		/* default to Generic* */
		return to_ref<Generic*>(x);
	}
	template<>
	STATIC_INLINE_SPECIALIZATION ref to_ref<Generic*>(Generic* x) {
		intptr_t tmp = reinterpret_cast<intptr_t>(x);
		#ifdef DEBUG
			if(tmp & tag_mask != 0) {
				throw_RangeError("Misaligned pointer");
			}
		#endif
		return ref(tmp + tag_traits<Generic*>::tag);
	}
	template<>
	STATIC_INLINE_SPECIALIZATION ref to_ref<Symbol*>(Symbol* x) {
		intptr_t tmp = reinterpret_cast<intptr_t>(x);
		#ifdef DEBUG
			if(tmp & tag_mask != 0) {
				throw_RangeError("Misaligned pointer");
			}
		#endif
		return ref(tmp + tag_traits<Symbol*>::tag);
	}
	template<>
	STATIC_INLINE_SPECIALIZATION ref to_ref<int>(int x) {
		#ifdef DEBUG
			#if (INT_MAX >= INTPTR_MAX) || (INT_MIN <= INTPTR_MIN)
				if(x < smallint_min || x > smallint_max) {
					throw_RangeError(
						"int out of range of smallint"
					);
				}
			#endif
		#endif
		intptr_t tmp = (((intptr_t) x) << tag_bits);
		return ref(tmp + tag_traits<int>::tag);
	}
	template<>
	STATIC_INLINE_SPECIALIZATION ref to_ref<UnicodeChar>(UnicodeChar x) {
		intptr_t tmp = x.dat << tag_bits;
		return ref(tmp + tag_traits<UnicodeChar>::tag);
	}

	/*no checking, even in debug mode... achtung!*/
	/*This function is used to convert an int computed using
	Object::to_a_scaled_int back to an Object::ref.  It is not
	intended to be used for any other int's.
	This function is intended for optimized smallint
	mathematics.
	*/
	static inline ref from_a_scaled_int(int x) {
                return ref((((intptr_t) x)<<tag_bits) + tag_traits<int>::tag);
	}

	static inline ref nil(void) {
		return ref();
	}
	static inline ref t(void) {
		return ref(t_value);
	}

/*-----------------------------------------------------------------------------
Tagged pointer checking
-----------------------------------------------------------------------------*/

	static inline bool _is_nil(ref obj) {
		return !obj;
	}
	static inline bool _is_t(ref obj) {
		return obj.dat == t_value;
	}

	template<typename T>
	static inline bool _is_a(ref obj) {
		if(tag_traits<T>::tag != 0x0) {
			return (obj.dat & tag_mask) == tag_traits<T>::tag;
		} else {
			return (obj.dat & tag_mask) == tag_traits<T>::tag
				&& !_is_nil(obj) && !_is_t(obj);
		}
	}

/*-----------------------------------------------------------------------------
Tagged pointer referencing
-----------------------------------------------------------------------------*/

	template<typename T>
	static inline T _as_a(ref obj) {
		#ifdef DEBUG
			if(!_is_a<T>(obj)) {
				throw_TypeError(obj,
					"incorrect type for pointer"
				);
			}
		#endif
		intptr_t tmp = obj.dat;
		return reinterpret_cast<T>(tmp - tag_traits<T>::tag);
		/*use subtraction instead of masking, in order to
		allow smart compilers to merge a field access with
		the tag removal. i.e. the pointers are pointers to
		structures, so they will be accessed via fields, and
		in all probability those fields will be at some
		offset from the actual structure address, meaning
		that the processor itself will perform an addition
		to access the field.  The smart compiler can then
		merge the addition of the field offset with the
		subtraction of the tag.
		*/
	}

	template<>
	STATIC_INLINE_SPECIALIZATION int _as_a<int>(ref obj) {
		#ifdef DEBUG
			if(!_is_a<int>(obj)) {
				throw_TypeError(obj,
					"incorrect type for small integer"
				);
			}
		#endif
		intptr_t tmp = obj.dat;
		return (int)(tmp >> tag_bits);
	}

	template<>
	STATIC_INLINE_SPECIALIZATION UnicodeChar _as_a<UnicodeChar>(ref obj) {
		uint32_t tmp = obj.dat;
		return UnicodeChar(tmp >> tag_bits);
	}

	/*no checking, even in debug mode... achtung!*/
	/*This function is used to convert a smallint Object::ref
	to a useable int that is equal to the "real" int, shifted
	to the left by the number of tag bits (i.e. scaled).  It
	should be used only for optimizing smallint math operations.
	*/
	static inline int to_a_scaled_int(ref obj) {
		intptr_t tmp = obj.dat;
		return (int)((tmp - tag_traits<int>::tag)>>tag_bits);
		/*use subtraction instead of masking, again to
		allow smart compilers to merge tag adding and
		subtracting.  For example the typical case would
		be something like:

		Object::ref result =
			Object::from_a_scaled_int(
				Object::to_a_scaled_int(a) +
				Object::to_a_scaled_int(b)
			);

		The above case can be reduced by the compiler to:

		intptr_t result =
			(tag_traits<int>::tag +
				a - tag_traits<int>::tag +
				b - tag_traits<int>::tag
			);

		It can then do some maths and cancel out a tag:

		intptr_t result = a + b - tag_traits<int>::tag;
		*/
	}

/*-----------------------------------------------------------------------------
Utility
-----------------------------------------------------------------------------*/

	static inline size_t round_up_to_alignment(size_t x) {
		return
		(x & tag_mask) ?      (x + alignment - (x & tag_mask)) :
		/*otherwise*/         x ;
	}

}

/*-----------------------------------------------------------------------------
Reflectors outside of the namespace
-----------------------------------------------------------------------------*/

template<typename T>
static inline bool is_a(Object::ref obj) {
	return Object::_is_a<T>(obj);
}
template<typename T>
static inline T as_a(Object::ref obj) {
	return Object::_as_a<T>(obj);
}
static inline bool is_nil(Object::ref obj) {
	return Object::_is_nil(obj);
}
static inline bool is_t(Object::ref obj) {
	return Object::_is_t(obj);
}

#endif //OBJECTS_H

<commit_msg>inc/objects.hpp: Made comparison functions `const`<commit_after>#ifndef OBJECTS_H
#define OBJECTS_H

/*
Defines an Object::ref type, which is a tagged pointer type.
Usage:
	Object::ref x = Object::to_ref(1);//smallint
	Object::ref y = Object::to_ref(new(hp) Generic()); //object
	if(is_a<int>(x)) {
		std::cout << "x = " << as_a<int>(x) << std::endl;
	}
	if(is_a<Generic*>(y)) {
		std::cout << "y.field = " << as_a<Generic*>(y)->field
			<< std::endl;
	}
*/

#include<stdint.h>
#include<climits>

#include"unichars.hpp"

#include"workarounds.hpp"

class Generic;
class Symbol;
class Cons;
class Closure;
class KClosure;

namespace Object {

/*-----------------------------------------------------------------------------
Declare
-----------------------------------------------------------------------------*/
	class ref;
	template<typename T> struct tag_traits;
	/*assume we won't ever need more than 7 bits of tag*/
	typedef unsigned char tag_type;

	template<typename T> static inline ref to_ref(T);
	template<typename T> static inline bool _is_a(ref);
	template<typename T> static inline T _as_a(ref);

	static inline ref t(void);
	static inline bool _is_t(ref);

	static inline ref nil(void);
	static inline bool _is_nil(ref);

	static inline ref from_a_scaled_int(int);
	static inline int to_a_scaled_int(ref);
}

void throw_TypeError(Object::ref, char const*);
void throw_RangeError(char const*);

template<typename T> static inline bool is_a(Object::ref);
template<typename T> static inline T as_a(Object::ref);

static inline bool is_t(Object::ref);

size_t hash_is(Object::ref);

namespace Object {

/*-----------------------------------------------------------------------------
Configuration
-----------------------------------------------------------------------------*/

	static const unsigned char tag_bits = 2;// can bump up to 3 maybe...

	template<> struct tag_traits<int> {
		static const tag_type tag = 0x1;
	};
	template<> struct tag_traits<Generic*> {
		static const tag_type tag = 0x0;
	};
	template<> struct tag_traits<Symbol*> {
		static const tag_type tag = 0x2;
	};
	template<> struct tag_traits<UnicodeChar> {
		static const tag_type tag = 0x3;
	};

/*-----------------------------------------------------------------------------
Provided information
-----------------------------------------------------------------------------*/

	static const tag_type alignment = 1 << tag_bits;
	static const tag_type tag_mask = alignment - 1;

	/*the real range is the smaller of the range of intptr_t
	shifted down by tag bits, or the range of the `int' type
	*/
	static const intptr_t smallint_min =
		(sizeof(int) >= sizeof(intptr_t)) ?
			INTPTR_MIN >> tag_bits :
		/*otherwise*/
			INT_MIN;
	static const intptr_t smallint_max =
		(sizeof(int) >= sizeof(intptr_t)) ?
			INTPTR_MAX >> tag_bits :
		/*otherwise*/
			INT_MAX;

	/*value for "t"*/
	static const intptr_t t_value = ~((intptr_t) tag_mask);

/*-----------------------------------------------------------------------------
The tagged pointer type
-----------------------------------------------------------------------------*/

	/*stefano prefers to use:
		typedef void* ref;
	or maybe:
		typedef intptr_t ref;
	I may change this later on, but for now
	I want to see whether the conceptual
	separation will help and if compilers,
	in general, will be smart enough to
	optimize away the structure.
	*/
	class ref {
	private:
		intptr_t dat;
		ref(intptr_t x) : dat(x) {}
	public:
		ref(void) : dat(0) {}
		inline bool operator==(ref b) const {
			return dat == b.dat;
		}
		inline bool operator!=(ref b) const {
			return dat != b.dat;
		}
		inline bool operator!(void) const {
			return dat == 0;
		}

		/*safe bool idiom*/
		typedef intptr_t (ref::*unspecified_bool_type);
		inline operator unspecified_bool_type(void) const {
			return dat != 0 ? &ref::dat : 0;
		}

		template<typename T> friend ref to_ref(T);
		template<typename T> friend bool _is_a(ref);
		template<typename T> friend T _as_a(ref);

		friend int to_a_scaled_int(ref);
		friend ref from_a_scaled_int(int);

		friend ref t(void);
		friend bool _is_t(ref);
		friend size_t (::hash_is)(Object::ref);
	};

/*-----------------------------------------------------------------------------
Tagged pointer factories
-----------------------------------------------------------------------------*/

	template<typename T>
	static inline ref to_ref(T x) {
		/* default to Generic* */
		return to_ref<Generic*>(x);
	}
	template<>
	STATIC_INLINE_SPECIALIZATION ref to_ref<Generic*>(Generic* x) {
		intptr_t tmp = reinterpret_cast<intptr_t>(x);
		#ifdef DEBUG
			if(tmp & tag_mask != 0) {
				throw_RangeError("Misaligned pointer");
			}
		#endif
		return ref(tmp + tag_traits<Generic*>::tag);
	}
	template<>
	STATIC_INLINE_SPECIALIZATION ref to_ref<Symbol*>(Symbol* x) {
		intptr_t tmp = reinterpret_cast<intptr_t>(x);
		#ifdef DEBUG
			if(tmp & tag_mask != 0) {
				throw_RangeError("Misaligned pointer");
			}
		#endif
		return ref(tmp + tag_traits<Symbol*>::tag);
	}
	template<>
	STATIC_INLINE_SPECIALIZATION ref to_ref<int>(int x) {
		#ifdef DEBUG
			#if (INT_MAX >= INTPTR_MAX) || (INT_MIN <= INTPTR_MIN)
				if(x < smallint_min || x > smallint_max) {
					throw_RangeError(
						"int out of range of smallint"
					);
				}
			#endif
		#endif
		intptr_t tmp = (((intptr_t) x) << tag_bits);
		return ref(tmp + tag_traits<int>::tag);
	}
	template<>
	STATIC_INLINE_SPECIALIZATION ref to_ref<UnicodeChar>(UnicodeChar x) {
		intptr_t tmp = x.dat << tag_bits;
		return ref(tmp + tag_traits<UnicodeChar>::tag);
	}

	/*no checking, even in debug mode... achtung!*/
	/*This function is used to convert an int computed using
	Object::to_a_scaled_int back to an Object::ref.  It is not
	intended to be used for any other int's.
	This function is intended for optimized smallint
	mathematics.
	*/
	static inline ref from_a_scaled_int(int x) {
                return ref((((intptr_t) x)<<tag_bits) + tag_traits<int>::tag);
	}

	static inline ref nil(void) {
		return ref();
	}
	static inline ref t(void) {
		return ref(t_value);
	}

/*-----------------------------------------------------------------------------
Tagged pointer checking
-----------------------------------------------------------------------------*/

	static inline bool _is_nil(ref obj) {
		return !obj;
	}
	static inline bool _is_t(ref obj) {
		return obj.dat == t_value;
	}

	template<typename T>
	static inline bool _is_a(ref obj) {
		if(tag_traits<T>::tag != 0x0) {
			return (obj.dat & tag_mask) == tag_traits<T>::tag;
		} else {
			return (obj.dat & tag_mask) == tag_traits<T>::tag
				&& !_is_nil(obj) && !_is_t(obj);
		}
	}

/*-----------------------------------------------------------------------------
Tagged pointer referencing
-----------------------------------------------------------------------------*/

	template<typename T>
	static inline T _as_a(ref obj) {
		#ifdef DEBUG
			if(!_is_a<T>(obj)) {
				throw_TypeError(obj,
					"incorrect type for pointer"
				);
			}
		#endif
		intptr_t tmp = obj.dat;
		return reinterpret_cast<T>(tmp - tag_traits<T>::tag);
		/*use subtraction instead of masking, in order to
		allow smart compilers to merge a field access with
		the tag removal. i.e. the pointers are pointers to
		structures, so they will be accessed via fields, and
		in all probability those fields will be at some
		offset from the actual structure address, meaning
		that the processor itself will perform an addition
		to access the field.  The smart compiler can then
		merge the addition of the field offset with the
		subtraction of the tag.
		*/
	}

	template<>
	STATIC_INLINE_SPECIALIZATION int _as_a<int>(ref obj) {
		#ifdef DEBUG
			if(!_is_a<int>(obj)) {
				throw_TypeError(obj,
					"incorrect type for small integer"
				);
			}
		#endif
		intptr_t tmp = obj.dat;
		return (int)(tmp >> tag_bits);
	}

	template<>
	STATIC_INLINE_SPECIALIZATION UnicodeChar _as_a<UnicodeChar>(ref obj) {
		uint32_t tmp = obj.dat;
		return UnicodeChar(tmp >> tag_bits);
	}

	/*no checking, even in debug mode... achtung!*/
	/*This function is used to convert a smallint Object::ref
	to a useable int that is equal to the "real" int, shifted
	to the left by the number of tag bits (i.e. scaled).  It
	should be used only for optimizing smallint math operations.
	*/
	static inline int to_a_scaled_int(ref obj) {
		intptr_t tmp = obj.dat;
		return (int)((tmp - tag_traits<int>::tag)>>tag_bits);
		/*use subtraction instead of masking, again to
		allow smart compilers to merge tag adding and
		subtracting.  For example the typical case would
		be something like:

		Object::ref result =
			Object::from_a_scaled_int(
				Object::to_a_scaled_int(a) +
				Object::to_a_scaled_int(b)
			);

		The above case can be reduced by the compiler to:

		intptr_t result =
			(tag_traits<int>::tag +
				a - tag_traits<int>::tag +
				b - tag_traits<int>::tag
			);

		It can then do some maths and cancel out a tag:

		intptr_t result = a + b - tag_traits<int>::tag;
		*/
	}

/*-----------------------------------------------------------------------------
Utility
-----------------------------------------------------------------------------*/

	static inline size_t round_up_to_alignment(size_t x) {
		return
		(x & tag_mask) ?      (x + alignment - (x & tag_mask)) :
		/*otherwise*/         x ;
	}

}

/*-----------------------------------------------------------------------------
Reflectors outside of the namespace
-----------------------------------------------------------------------------*/

template<typename T>
static inline bool is_a(Object::ref obj) {
	return Object::_is_a<T>(obj);
}
template<typename T>
static inline T as_a(Object::ref obj) {
	return Object::_as_a<T>(obj);
}
static inline bool is_nil(Object::ref obj) {
	return Object::_is_nil(obj);
}
static inline bool is_t(Object::ref obj) {
	return Object::_is_t(obj);
}

#endif //OBJECTS_H

<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkGenericVertexAttributeMapping.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
#include "vtkGenericVertexAttributeMapping.h"

#include "vtkObjectFactory.h"
#include <string>
#include <vector>

#include <vtksys/ios/sstream>

class vtkGenericVertexAttributeMapping::vtkInternal
{
public:
  struct vtkInfo
    {
    std::string AttributeName;
    std::string ArrayName;
    int FieldAssociation;
    int Component;
    int TextureUnit;
    };

  typedef std::vector<vtkInfo> VectorType;
  VectorType Mappings;
};

vtkStandardNewMacro(vtkGenericVertexAttributeMapping);
//----------------------------------------------------------------------------
vtkGenericVertexAttributeMapping::vtkGenericVertexAttributeMapping()
{
  this->Internal = new vtkInternal();
}

//----------------------------------------------------------------------------
vtkGenericVertexAttributeMapping::~vtkGenericVertexAttributeMapping()
{
  delete this->Internal;
}

//----------------------------------------------------------------------------
void vtkGenericVertexAttributeMapping::AddMapping(
  const char* attributeName, const char* arrayName, int fieldAssociation,
  int component)
{
  if (!attributeName || !arrayName)
    {
    vtkErrorMacro("arrayName and attributeName cannot be null.");
    return;
    }

  if (this->RemoveMapping(attributeName))
    {
    vtkWarningMacro("Replacing existsing mapping for attribute "
      << attributeName);
    }

  vtkInternal::vtkInfo info;
  info.AttributeName = attributeName;
  info.ArrayName = arrayName;
  info.FieldAssociation = fieldAssociation;
  info.Component = component;
  info.TextureUnit = -1;
  this->Internal->Mappings.push_back(info);
}

//----------------------------------------------------------------------------
void vtkGenericVertexAttributeMapping::AddMapping(
  int unit, const char* arrayName, int fieldAssociation,
  int component)
{
  vtksys_ios::ostringstream attributeName;
  attributeName << unit;

  if (this->RemoveMapping(attributeName.str().c_str()))
    {
    vtkWarningMacro("Replacing existsing mapping for attribute "
      << attributeName);
    }

  vtkInternal::vtkInfo info;
  info.AttributeName = attributeName.str().c_str();
  info.ArrayName = arrayName;
  info.FieldAssociation = fieldAssociation;
  info.Component = component;
  info.TextureUnit = unit;
  this->Internal->Mappings.push_back(info);
}

//----------------------------------------------------------------------------
bool vtkGenericVertexAttributeMapping::RemoveMapping(const char* attributeName)
{
  vtkInternal::VectorType::iterator iter;
  for (iter=this->Internal->Mappings.begin();
    iter != this->Internal->Mappings.end(); ++iter)
    {
    if (iter->AttributeName == attributeName)
      {
      this->Internal->Mappings.erase(iter);
      return true;
      }
    }
  return false;
}

//----------------------------------------------------------------------------
void vtkGenericVertexAttributeMapping::RemoveAllMappings()
{
  this->Internal->Mappings.clear();
}

//----------------------------------------------------------------------------
unsigned int vtkGenericVertexAttributeMapping::GetNumberOfMappings()
{
  return static_cast<unsigned int>(this->Internal->Mappings.size());
}

//----------------------------------------------------------------------------
const char* vtkGenericVertexAttributeMapping::GetAttributeName(unsigned int index)
{
  if (index >= this->Internal->Mappings.size())
    {
    vtkErrorMacro("Invalid index " << index);
    return 0;
    }
  return this->Internal->Mappings[index].AttributeName.c_str();
}

//----------------------------------------------------------------------------
const char* vtkGenericVertexAttributeMapping::GetArrayName(unsigned int index)
{
  if (index >= this->Internal->Mappings.size())
    {
    vtkErrorMacro("Invalid index " << index);
    return 0;
    }
  return this->Internal->Mappings[index].ArrayName.c_str();
}

//----------------------------------------------------------------------------
int vtkGenericVertexAttributeMapping::GetFieldAssociation(unsigned int index)
{
  if (index >= this->Internal->Mappings.size())
    {
    vtkErrorMacro("Invalid index " << index);
    return 0;
    }
  return this->Internal->Mappings[index].FieldAssociation;
}

//----------------------------------------------------------------------------
int vtkGenericVertexAttributeMapping::GetComponent(unsigned int index)
{
  if (index >= this->Internal->Mappings.size())
    {
    vtkErrorMacro("Invalid index " << index);
    return 0;
    }
  return this->Internal->Mappings[index].Component;
}

//----------------------------------------------------------------------------
int vtkGenericVertexAttributeMapping::GetTextureUnit(unsigned int index)
{
  if (index >= this->Internal->Mappings.size())
    {
    vtkErrorMacro("Invalid index " << index);
    return 0;
    }
  return this->Internal->Mappings[index].TextureUnit;
}

//----------------------------------------------------------------------------
void vtkGenericVertexAttributeMapping::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os, indent);
   vtkInternal::VectorType::iterator iter;
  for (iter=this->Internal->Mappings.begin();
    iter != this->Internal->Mappings.end(); ++iter)
    {
    os << indent << "Mapping: "
      << iter->AttributeName.c_str() << ", "
      << iter->ArrayName.c_str() << ", "
      << iter->FieldAssociation << ", "
      << iter->Component << endl;
    }
}

<commit_msg>Fixed spelling in debug string.<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkGenericVertexAttributeMapping.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
#include "vtkGenericVertexAttributeMapping.h"

#include "vtkObjectFactory.h"
#include <string>
#include <vector>

#include <vtksys/ios/sstream>

class vtkGenericVertexAttributeMapping::vtkInternal
{
public:
  struct vtkInfo
    {
    std::string AttributeName;
    std::string ArrayName;
    int FieldAssociation;
    int Component;
    int TextureUnit;
    };

  typedef std::vector<vtkInfo> VectorType;
  VectorType Mappings;
};

vtkStandardNewMacro(vtkGenericVertexAttributeMapping);
//----------------------------------------------------------------------------
vtkGenericVertexAttributeMapping::vtkGenericVertexAttributeMapping()
{
  this->Internal = new vtkInternal();
}

//----------------------------------------------------------------------------
vtkGenericVertexAttributeMapping::~vtkGenericVertexAttributeMapping()
{
  delete this->Internal;
}

//----------------------------------------------------------------------------
void vtkGenericVertexAttributeMapping::AddMapping(
  const char* attributeName, const char* arrayName, int fieldAssociation,
  int component)
{
  if (!attributeName || !arrayName)
    {
    vtkErrorMacro("arrayName and attributeName cannot be null.");
    return;
    }

  if (this->RemoveMapping(attributeName))
    {
    vtkWarningMacro("Replacing existing mapping for attribute "
      << attributeName);
    }

  vtkInternal::vtkInfo info;
  info.AttributeName = attributeName;
  info.ArrayName = arrayName;
  info.FieldAssociation = fieldAssociation;
  info.Component = component;
  info.TextureUnit = -1;
  this->Internal->Mappings.push_back(info);
}

//----------------------------------------------------------------------------
void vtkGenericVertexAttributeMapping::AddMapping(
  int unit, const char* arrayName, int fieldAssociation,
  int component)
{
  vtksys_ios::ostringstream attributeName;
  attributeName << unit;

  if (this->RemoveMapping(attributeName.str().c_str()))
    {
    vtkWarningMacro("Replacing existing mapping for attribute "
      << attributeName);
    }

  vtkInternal::vtkInfo info;
  info.AttributeName = attributeName.str().c_str();
  info.ArrayName = arrayName;
  info.FieldAssociation = fieldAssociation;
  info.Component = component;
  info.TextureUnit = unit;
  this->Internal->Mappings.push_back(info);
}

//----------------------------------------------------------------------------
bool vtkGenericVertexAttributeMapping::RemoveMapping(const char* attributeName)
{
  vtkInternal::VectorType::iterator iter;
  for (iter=this->Internal->Mappings.begin();
    iter != this->Internal->Mappings.end(); ++iter)
    {
    if (iter->AttributeName == attributeName)
      {
      this->Internal->Mappings.erase(iter);
      return true;
      }
    }
  return false;
}

//----------------------------------------------------------------------------
void vtkGenericVertexAttributeMapping::RemoveAllMappings()
{
  this->Internal->Mappings.clear();
}

//----------------------------------------------------------------------------
unsigned int vtkGenericVertexAttributeMapping::GetNumberOfMappings()
{
  return static_cast<unsigned int>(this->Internal->Mappings.size());
}

//----------------------------------------------------------------------------
const char* vtkGenericVertexAttributeMapping::GetAttributeName(unsigned int index)
{
  if (index >= this->Internal->Mappings.size())
    {
    vtkErrorMacro("Invalid index " << index);
    return 0;
    }
  return this->Internal->Mappings[index].AttributeName.c_str();
}

//----------------------------------------------------------------------------
const char* vtkGenericVertexAttributeMapping::GetArrayName(unsigned int index)
{
  if (index >= this->Internal->Mappings.size())
    {
    vtkErrorMacro("Invalid index " << index);
    return 0;
    }
  return this->Internal->Mappings[index].ArrayName.c_str();
}

//----------------------------------------------------------------------------
int vtkGenericVertexAttributeMapping::GetFieldAssociation(unsigned int index)
{
  if (index >= this->Internal->Mappings.size())
    {
    vtkErrorMacro("Invalid index " << index);
    return 0;
    }
  return this->Internal->Mappings[index].FieldAssociation;
}

//----------------------------------------------------------------------------
int vtkGenericVertexAttributeMapping::GetComponent(unsigned int index)
{
  if (index >= this->Internal->Mappings.size())
    {
    vtkErrorMacro("Invalid index " << index);
    return 0;
    }
  return this->Internal->Mappings[index].Component;
}

//----------------------------------------------------------------------------
int vtkGenericVertexAttributeMapping::GetTextureUnit(unsigned int index)
{
  if (index >= this->Internal->Mappings.size())
    {
    vtkErrorMacro("Invalid index " << index);
    return 0;
    }
  return this->Internal->Mappings[index].TextureUnit;
}

//----------------------------------------------------------------------------
void vtkGenericVertexAttributeMapping::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os, indent);
   vtkInternal::VectorType::iterator iter;
  for (iter=this->Internal->Mappings.begin();
    iter != this->Internal->Mappings.end(); ++iter)
    {
    os << indent << "Mapping: "
      << iter->AttributeName.c_str() << ", "
      << iter->ArrayName.c_str() << ", "
      << iter->FieldAssociation << ", "
      << iter->Component << endl;
    }
}

<|endoftext|>


<commit_before>// Copyright (c) 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/compiler_specific.h"
#include "base/lock.h"
#include "base/platform_thread.h"
#include "base/simple_thread.h"
#include "base/thread_collision_warner.h"
#include "testing/gtest/include/gtest/gtest.h"

// '' : local class member function does not have a body
MSVC_PUSH_DISABLE_WARNING(4822)

namespace {

// This is the asserter used with ThreadCollisionWarner instead of the default
// DCheckAsserter. The method fail_state is used to know if a collision took
// place.
class AssertReporter : public base::AsserterBase {
 public:
  AssertReporter()
      : failed_(false) {}

  virtual void warn() {
    failed_ = true;
  }

  virtual ~AssertReporter() {}

  bool fail_state() const { return failed_; }
  void reset() { failed_ = false; }

 private:
  bool failed_;
};

}  // namespace

TEST(ThreadCollisionTest, BookCriticalSection) {
  AssertReporter* local_reporter = new AssertReporter();

  base::ThreadCollisionWarner warner(local_reporter);
  EXPECT_FALSE(local_reporter->fail_state());

  {  // Pin section.
    DFAKE_SCOPED_LOCK_THREAD_LOCKED(warner);
    EXPECT_FALSE(local_reporter->fail_state());
    {  // Pin section.
      DFAKE_SCOPED_LOCK_THREAD_LOCKED(warner);
      EXPECT_FALSE(local_reporter->fail_state());
    }
  }
}

TEST(ThreadCollisionTest, ScopedRecursiveBookCriticalSection) {
  AssertReporter* local_reporter = new AssertReporter();

  base::ThreadCollisionWarner warner(local_reporter);
  EXPECT_FALSE(local_reporter->fail_state());

  {  // Pin section.
    DFAKE_SCOPED_RECURSIVE_LOCK(warner);
    EXPECT_FALSE(local_reporter->fail_state());
    {  // Pin section again (allowed by DFAKE_SCOPED_RECURSIVE_LOCK)
      DFAKE_SCOPED_RECURSIVE_LOCK(warner);
      EXPECT_FALSE(local_reporter->fail_state());
    }  // Unpin section.
  }  // Unpin section.

  // Check that section is not pinned
  {  // Pin section.
    DFAKE_SCOPED_LOCK(warner);
    EXPECT_FALSE(local_reporter->fail_state());
  }  // Unpin section.
}

TEST(ThreadCollisionTest, ScopedBookCriticalSection) {
  AssertReporter* local_reporter = new AssertReporter();

  base::ThreadCollisionWarner warner(local_reporter);
  EXPECT_FALSE(local_reporter->fail_state());

  {  // Pin section.
    DFAKE_SCOPED_LOCK(warner);
    EXPECT_FALSE(local_reporter->fail_state());
  }  // Unpin section.

  {  // Pin section.
    DFAKE_SCOPED_LOCK(warner);
    EXPECT_FALSE(local_reporter->fail_state());
    {
      // Pin section again (not allowed by DFAKE_SCOPED_LOCK)
      DFAKE_SCOPED_LOCK(warner);
#if !defined(NDEBUG)
      EXPECT_TRUE(local_reporter->fail_state());
#else
      EXPECT_FALSE(local_reporter->fail_state());
#endif
      // Reset the status of warner for further tests.
      local_reporter->reset();
    }  // Unpin section.
  }  // Unpin section.

  {
    // Pin section.
    DFAKE_SCOPED_LOCK(warner);
    EXPECT_FALSE(local_reporter->fail_state());
  }  // Unpin section.
}

TEST(ThreadCollisionTest, MTBookCriticalSectionTest) {
  class NonThreadSafeQueue {
   public:
    explicit NonThreadSafeQueue(base::AsserterBase* asserter)
#if !defined(NDEBUG)
        : push_pop_(asserter) {
#else
    {
      delete asserter;
#endif
    }

    void push(int value) {
      DFAKE_SCOPED_LOCK_THREAD_LOCKED(push_pop_);
    }

    int pop() {
      DFAKE_SCOPED_LOCK_THREAD_LOCKED(push_pop_);
      return 0;
    }

   private:
    DFAKE_MUTEX(push_pop_);

    DISALLOW_COPY_AND_ASSIGN(NonThreadSafeQueue);
  };

  class QueueUser : public base::DelegateSimpleThread::Delegate {
   public:
    explicit QueueUser(NonThreadSafeQueue& queue)
        : queue_(queue) {}

    virtual void Run() {
      queue_.push(0);
      queue_.pop();
    }

   private:
    NonThreadSafeQueue& queue_;
  };

  AssertReporter* local_reporter = new AssertReporter();

  NonThreadSafeQueue queue(local_reporter);

  QueueUser queue_user_a(queue);
  QueueUser queue_user_b(queue);

  base::DelegateSimpleThread thread_a(&queue_user_a, "queue_user_thread_a");
  base::DelegateSimpleThread thread_b(&queue_user_b, "queue_user_thread_b");

  thread_a.Start();
  thread_b.Start();

  thread_a.Join();
  thread_b.Join();

#if !defined(NDEBUG)
  EXPECT_TRUE(local_reporter->fail_state());
#else
  EXPECT_FALSE(local_reporter->fail_state());
#endif
}

TEST(ThreadCollisionTest, MTScopedBookCriticalSectionTest) {
  // Queue with a 5 seconds push execution time, hopefuly the two used threads
  // in the test will enter the push at same time.
  class NonThreadSafeQueue {
   public:
    explicit NonThreadSafeQueue(base::AsserterBase* asserter)
#if !defined(NDEBUG)
        : push_pop_(asserter) {
#else
    {
      delete asserter;
#endif
    }

    void push(int value) {
      DFAKE_SCOPED_LOCK(push_pop_);
      PlatformThread::Sleep(5000);
    }

    int pop() {
      DFAKE_SCOPED_LOCK(push_pop_);
      return 0;
    }

   private:
    DFAKE_MUTEX(push_pop_);

    DISALLOW_COPY_AND_ASSIGN(NonThreadSafeQueue);
  };

  class QueueUser : public base::DelegateSimpleThread::Delegate {
   public:
    explicit QueueUser(NonThreadSafeQueue& queue)
        : queue_(queue) {}

    virtual void Run() {
      queue_.push(0);
      queue_.pop();
    }

   private:
    NonThreadSafeQueue& queue_;
  };

  AssertReporter* local_reporter = new AssertReporter();

  NonThreadSafeQueue queue(local_reporter);

  QueueUser queue_user_a(queue);
  QueueUser queue_user_b(queue);

  base::DelegateSimpleThread thread_a(&queue_user_a, "queue_user_thread_a");
  base::DelegateSimpleThread thread_b(&queue_user_b, "queue_user_thread_b");

  thread_a.Start();
  thread_b.Start();

  thread_a.Join();
  thread_b.Join();

#if !defined(NDEBUG)
  EXPECT_TRUE(local_reporter->fail_state());
#else
  EXPECT_FALSE(local_reporter->fail_state());
#endif
}

TEST(ThreadCollisionTest, MTSynchedScopedBookCriticalSectionTest) {
  // Queue with a 5 seconds push execution time, hopefuly the two used threads
  // in the test will enter the push at same time.
  class NonThreadSafeQueue {
   public:
    explicit NonThreadSafeQueue(base::AsserterBase* asserter)
#if !defined(NDEBUG)
        : push_pop_(asserter) {
#else
    {
      delete asserter;
#endif
    }

    void push(int value) {
      DFAKE_SCOPED_LOCK(push_pop_);
      PlatformThread::Sleep(5000);
    }

    int pop() {
      DFAKE_SCOPED_LOCK(push_pop_);
      return 0;
    }

   private:
    DFAKE_MUTEX(push_pop_);

    DISALLOW_COPY_AND_ASSIGN(NonThreadSafeQueue);
  };

  // This time the QueueUser class protects the non thread safe queue with
  // a lock.
  class QueueUser : public base::DelegateSimpleThread::Delegate {
   public:
    QueueUser(NonThreadSafeQueue& queue, Lock& lock)
        : queue_(queue),
          lock_(lock) {}

    virtual void Run() {
      {
        AutoLock auto_lock(lock_);
        queue_.push(0);
      }
      {
        AutoLock auto_lock(lock_);
        queue_.pop();
      }
    }
   private:
    NonThreadSafeQueue& queue_;
    Lock& lock_;
  };

  AssertReporter* local_reporter = new AssertReporter();

  NonThreadSafeQueue queue(local_reporter);

  Lock lock;

  QueueUser queue_user_a(queue, lock);
  QueueUser queue_user_b(queue, lock);

  base::DelegateSimpleThread thread_a(&queue_user_a, "queue_user_thread_a");
  base::DelegateSimpleThread thread_b(&queue_user_b, "queue_user_thread_b");

  thread_a.Start();
  thread_b.Start();

  thread_a.Join();
  thread_b.Join();

  EXPECT_FALSE(local_reporter->fail_state());
}

TEST(ThreadCollisionTest, MTSynchedScopedRecursiveBookCriticalSectionTest) {
  // Queue with a 5 seconds push execution time, hopefuly the two used threads
  // in the test will enter the push at same time.
  class NonThreadSafeQueue {
   public:
    explicit NonThreadSafeQueue(base::AsserterBase* asserter)
#if !defined(NDEBUG)
        : push_pop_(asserter) {
#else
    {
      delete asserter;
#endif
    }

    void push(int) {
      DFAKE_SCOPED_RECURSIVE_LOCK(push_pop_);
      bar();
      PlatformThread::Sleep(5000);
    }

    int pop() {
      DFAKE_SCOPED_RECURSIVE_LOCK(push_pop_);
      return 0;
    }

    void bar() {
      DFAKE_SCOPED_RECURSIVE_LOCK(push_pop_);
    }

   private:
    DFAKE_MUTEX(push_pop_);

    DISALLOW_COPY_AND_ASSIGN(NonThreadSafeQueue);
  };

  // This time the QueueUser class protects the non thread safe queue with
  // a lock.
  class QueueUser : public base::DelegateSimpleThread::Delegate {
   public:
    QueueUser(NonThreadSafeQueue& queue, Lock& lock)
        : queue_(queue),
          lock_(lock) {}

    virtual void Run() {
      {
        AutoLock auto_lock(lock_);
        queue_.push(0);
      }
      {
        AutoLock auto_lock(lock_);
        queue_.bar();
      }
      {
        AutoLock auto_lock(lock_);
        queue_.pop();
      }
    }
   private:
    NonThreadSafeQueue& queue_;
    Lock& lock_;
  };

  AssertReporter* local_reporter = new AssertReporter();

  NonThreadSafeQueue queue(local_reporter);

  Lock lock;

  QueueUser queue_user_a(queue, lock);
  QueueUser queue_user_b(queue, lock);

  base::DelegateSimpleThread thread_a(&queue_user_a, "queue_user_thread_a");
  base::DelegateSimpleThread thread_b(&queue_user_b, "queue_user_thread_b");

  thread_a.Start();
  thread_b.Start();

  thread_a.Join();
  thread_b.Join();

  EXPECT_FALSE(local_reporter->fail_state());
}
<commit_msg>Reduce the amount of #ifdef. Review URL: http://codereview.chromium.org/18852<commit_after>// Copyright (c) 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/compiler_specific.h"
#include "base/lock.h"
#include "base/platform_thread.h"
#include "base/simple_thread.h"
#include "base/thread_collision_warner.h"
#include "testing/gtest/include/gtest/gtest.h"

// '' : local class member function does not have a body
MSVC_PUSH_DISABLE_WARNING(4822)

#if defined(NDEBUG)

// Would cause a memory leak otherwise.
#undef DFAKE_MUTEX
#define DFAKE_MUTEX(obj) scoped_ptr<base::AsserterBase> obj

// In Release, we expect the AsserterBase::warn() to not happen.
#define EXPECT_NDEBUG_FALSE_DEBUG_TRUE EXPECT_FALSE

#else

// In Debug, we expect the AsserterBase::warn() to happen.
#define EXPECT_NDEBUG_FALSE_DEBUG_TRUE EXPECT_TRUE

#endif

namespace {

// This is the asserter used with ThreadCollisionWarner instead of the default
// DCheckAsserter. The method fail_state is used to know if a collision took
// place.
class AssertReporter : public base::AsserterBase {
 public:
  AssertReporter()
      : failed_(false) {}

  virtual void warn() {
    failed_ = true;
  }

  virtual ~AssertReporter() {}

  bool fail_state() const { return failed_; }
  void reset() { failed_ = false; }

 private:
  bool failed_;
};

}  // namespace

TEST(ThreadCollisionTest, BookCriticalSection) {
  AssertReporter* local_reporter = new AssertReporter();

  base::ThreadCollisionWarner warner(local_reporter);
  EXPECT_FALSE(local_reporter->fail_state());

  {  // Pin section.
    DFAKE_SCOPED_LOCK_THREAD_LOCKED(warner);
    EXPECT_FALSE(local_reporter->fail_state());
    {  // Pin section.
      DFAKE_SCOPED_LOCK_THREAD_LOCKED(warner);
      EXPECT_FALSE(local_reporter->fail_state());
    }
  }
}

TEST(ThreadCollisionTest, ScopedRecursiveBookCriticalSection) {
  AssertReporter* local_reporter = new AssertReporter();

  base::ThreadCollisionWarner warner(local_reporter);
  EXPECT_FALSE(local_reporter->fail_state());

  {  // Pin section.
    DFAKE_SCOPED_RECURSIVE_LOCK(warner);
    EXPECT_FALSE(local_reporter->fail_state());
    {  // Pin section again (allowed by DFAKE_SCOPED_RECURSIVE_LOCK)
      DFAKE_SCOPED_RECURSIVE_LOCK(warner);
      EXPECT_FALSE(local_reporter->fail_state());
    }  // Unpin section.
  }  // Unpin section.

  // Check that section is not pinned
  {  // Pin section.
    DFAKE_SCOPED_LOCK(warner);
    EXPECT_FALSE(local_reporter->fail_state());
  }  // Unpin section.
}

TEST(ThreadCollisionTest, ScopedBookCriticalSection) {
  AssertReporter* local_reporter = new AssertReporter();

  base::ThreadCollisionWarner warner(local_reporter);
  EXPECT_FALSE(local_reporter->fail_state());

  {  // Pin section.
    DFAKE_SCOPED_LOCK(warner);
    EXPECT_FALSE(local_reporter->fail_state());
  }  // Unpin section.

  {  // Pin section.
    DFAKE_SCOPED_LOCK(warner);
    EXPECT_FALSE(local_reporter->fail_state());
    {
      // Pin section again (not allowed by DFAKE_SCOPED_LOCK)
      DFAKE_SCOPED_LOCK(warner);
      EXPECT_NDEBUG_FALSE_DEBUG_TRUE(local_reporter->fail_state());
      // Reset the status of warner for further tests.
      local_reporter->reset();
    }  // Unpin section.
  }  // Unpin section.

  {
    // Pin section.
    DFAKE_SCOPED_LOCK(warner);
    EXPECT_FALSE(local_reporter->fail_state());
  }  // Unpin section.
}

TEST(ThreadCollisionTest, MTBookCriticalSectionTest) {
  class NonThreadSafeQueue {
   public:
    explicit NonThreadSafeQueue(base::AsserterBase* asserter)
        : push_pop_(asserter) {
    }

    void push(int value) {
      DFAKE_SCOPED_LOCK_THREAD_LOCKED(push_pop_);
    }

    int pop() {
      DFAKE_SCOPED_LOCK_THREAD_LOCKED(push_pop_);
      return 0;
    }

   private:
    DFAKE_MUTEX(push_pop_);

    DISALLOW_COPY_AND_ASSIGN(NonThreadSafeQueue);
  };

  class QueueUser : public base::DelegateSimpleThread::Delegate {
   public:
    explicit QueueUser(NonThreadSafeQueue& queue)
        : queue_(queue) {}

    virtual void Run() {
      queue_.push(0);
      queue_.pop();
    }

   private:
    NonThreadSafeQueue& queue_;
  };

  AssertReporter* local_reporter = new AssertReporter();

  NonThreadSafeQueue queue(local_reporter);

  QueueUser queue_user_a(queue);
  QueueUser queue_user_b(queue);

  base::DelegateSimpleThread thread_a(&queue_user_a, "queue_user_thread_a");
  base::DelegateSimpleThread thread_b(&queue_user_b, "queue_user_thread_b");

  thread_a.Start();
  thread_b.Start();

  thread_a.Join();
  thread_b.Join();

  EXPECT_NDEBUG_FALSE_DEBUG_TRUE(local_reporter->fail_state());
}

TEST(ThreadCollisionTest, MTScopedBookCriticalSectionTest) {
  // Queue with a 5 seconds push execution time, hopefuly the two used threads
  // in the test will enter the push at same time.
  class NonThreadSafeQueue {
   public:
    explicit NonThreadSafeQueue(base::AsserterBase* asserter)
        : push_pop_(asserter) {
    }

    void push(int value) {
      DFAKE_SCOPED_LOCK(push_pop_);
      PlatformThread::Sleep(5000);
    }

    int pop() {
      DFAKE_SCOPED_LOCK(push_pop_);
      return 0;
    }

   private:
    DFAKE_MUTEX(push_pop_);

    DISALLOW_COPY_AND_ASSIGN(NonThreadSafeQueue);
  };

  class QueueUser : public base::DelegateSimpleThread::Delegate {
   public:
    explicit QueueUser(NonThreadSafeQueue& queue)
        : queue_(queue) {}

    virtual void Run() {
      queue_.push(0);
      queue_.pop();
    }

   private:
    NonThreadSafeQueue& queue_;
  };

  AssertReporter* local_reporter = new AssertReporter();

  NonThreadSafeQueue queue(local_reporter);

  QueueUser queue_user_a(queue);
  QueueUser queue_user_b(queue);

  base::DelegateSimpleThread thread_a(&queue_user_a, "queue_user_thread_a");
  base::DelegateSimpleThread thread_b(&queue_user_b, "queue_user_thread_b");

  thread_a.Start();
  thread_b.Start();

  thread_a.Join();
  thread_b.Join();

  EXPECT_NDEBUG_FALSE_DEBUG_TRUE(local_reporter->fail_state());
}

TEST(ThreadCollisionTest, MTSynchedScopedBookCriticalSectionTest) {
  // Queue with a 5 seconds push execution time, hopefuly the two used threads
  // in the test will enter the push at same time.
  class NonThreadSafeQueue {
   public:
    explicit NonThreadSafeQueue(base::AsserterBase* asserter)
        : push_pop_(asserter) {
    }

    void push(int value) {
      DFAKE_SCOPED_LOCK(push_pop_);
      PlatformThread::Sleep(5000);
    }

    int pop() {
      DFAKE_SCOPED_LOCK(push_pop_);
      return 0;
    }

   private:
    DFAKE_MUTEX(push_pop_);

    DISALLOW_COPY_AND_ASSIGN(NonThreadSafeQueue);
  };

  // This time the QueueUser class protects the non thread safe queue with
  // a lock.
  class QueueUser : public base::DelegateSimpleThread::Delegate {
   public:
    QueueUser(NonThreadSafeQueue& queue, Lock& lock)
        : queue_(queue),
          lock_(lock) {}

    virtual void Run() {
      {
        AutoLock auto_lock(lock_);
        queue_.push(0);
      }
      {
        AutoLock auto_lock(lock_);
        queue_.pop();
      }
    }
   private:
    NonThreadSafeQueue& queue_;
    Lock& lock_;
  };

  AssertReporter* local_reporter = new AssertReporter();

  NonThreadSafeQueue queue(local_reporter);

  Lock lock;

  QueueUser queue_user_a(queue, lock);
  QueueUser queue_user_b(queue, lock);

  base::DelegateSimpleThread thread_a(&queue_user_a, "queue_user_thread_a");
  base::DelegateSimpleThread thread_b(&queue_user_b, "queue_user_thread_b");

  thread_a.Start();
  thread_b.Start();

  thread_a.Join();
  thread_b.Join();

  EXPECT_FALSE(local_reporter->fail_state());
}

TEST(ThreadCollisionTest, MTSynchedScopedRecursiveBookCriticalSectionTest) {
  // Queue with a 5 seconds push execution time, hopefuly the two used threads
  // in the test will enter the push at same time.
  class NonThreadSafeQueue {
   public:
    explicit NonThreadSafeQueue(base::AsserterBase* asserter)
        : push_pop_(asserter) {
    }

    void push(int) {
      DFAKE_SCOPED_RECURSIVE_LOCK(push_pop_);
      bar();
      PlatformThread::Sleep(5000);
    }

    int pop() {
      DFAKE_SCOPED_RECURSIVE_LOCK(push_pop_);
      return 0;
    }

    void bar() {
      DFAKE_SCOPED_RECURSIVE_LOCK(push_pop_);
    }

   private:
    DFAKE_MUTEX(push_pop_);

    DISALLOW_COPY_AND_ASSIGN(NonThreadSafeQueue);
  };

  // This time the QueueUser class protects the non thread safe queue with
  // a lock.
  class QueueUser : public base::DelegateSimpleThread::Delegate {
   public:
    QueueUser(NonThreadSafeQueue& queue, Lock& lock)
        : queue_(queue),
          lock_(lock) {}

    virtual void Run() {
      {
        AutoLock auto_lock(lock_);
        queue_.push(0);
      }
      {
        AutoLock auto_lock(lock_);
        queue_.bar();
      }
      {
        AutoLock auto_lock(lock_);
        queue_.pop();
      }
    }
   private:
    NonThreadSafeQueue& queue_;
    Lock& lock_;
  };

  AssertReporter* local_reporter = new AssertReporter();

  NonThreadSafeQueue queue(local_reporter);

  Lock lock;

  QueueUser queue_user_a(queue, lock);
  QueueUser queue_user_b(queue, lock);

  base::DelegateSimpleThread thread_a(&queue_user_a, "queue_user_thread_a");
  base::DelegateSimpleThread thread_b(&queue_user_b, "queue_user_thread_b");

  thread_a.Start();
  thread_b.Start();

  thread_a.Join();
  thread_b.Join();

  EXPECT_FALSE(local_reporter->fail_state());
}
<|endoftext|>


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

#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "webrtc/modules/interface/module.h"
#include "webrtc/modules/utility/source/process_thread_impl.h"
#include "webrtc/system_wrappers/interface/tick_util.h"

namespace webrtc {

using ::testing::_;
using ::testing::DoAll;
using ::testing::InSequence;
using ::testing::Invoke;
using ::testing::Return;
using ::testing::SetArgPointee;

class MockModule : public Module {
 public:
  MOCK_METHOD0(TimeUntilNextProcess, int64_t());
  MOCK_METHOD0(Process, int32_t());
};

ACTION_P(SetEvent, event) {
  event->Set();
}

ACTION_P(Increment, counter) {
  ++(*counter);
}

ACTION_P(SetTimestamp, ptr) {
  *ptr = TickTime::MillisecondTimestamp();
}

TEST(ProcessThreadImpl, StartStop) {
  ProcessThreadImpl thread;
  EXPECT_EQ(0, thread.Start());
  EXPECT_EQ(0, thread.Stop());
}

TEST(ProcessThreadImpl, MultipleStartStop) {
  ProcessThreadImpl thread;
  for (int i = 0; i < 5; ++i) {
    EXPECT_EQ(0, thread.Start());
    EXPECT_EQ(0, thread.Stop());
  }
}

// Verifies that we get at least call back to Process() on the worker thread.
TEST(ProcessThreadImpl, ProcessCall) {
  ProcessThreadImpl thread;
  ASSERT_EQ(0, thread.Start());

  rtc::scoped_ptr<EventWrapper> event(EventWrapper::Create());

  MockModule module;
  EXPECT_CALL(module, TimeUntilNextProcess()).WillRepeatedly(Return(0));
  EXPECT_CALL(module, Process())
      .WillOnce(DoAll(SetEvent(event.get()), Return(0)))
      .WillRepeatedly(Return(0));

  ASSERT_EQ(0, thread.RegisterModule(&module));
  EXPECT_EQ(kEventSignaled, event->Wait(100));
  EXPECT_EQ(0, thread.Stop());
}

// Same as ProcessCall except the module is registered before the
// call to Start().
TEST(ProcessThreadImpl, ProcessCall2) {
  ProcessThreadImpl thread;
  rtc::scoped_ptr<EventWrapper> event(EventWrapper::Create());

  MockModule module;
  EXPECT_CALL(module, TimeUntilNextProcess()).WillRepeatedly(Return(0));
  EXPECT_CALL(module, Process())
      .WillOnce(DoAll(SetEvent(event.get()), Return(0)))
      .WillRepeatedly(Return(0));

  ASSERT_EQ(0, thread.RegisterModule(&module));
  ASSERT_EQ(thread.Start(), 0);
  EXPECT_EQ(kEventSignaled, event->Wait(100));
  EXPECT_EQ(thread.Stop(), 0);
}

// Tests setting up a module for callbacks and then unregister that module.
// After unregistration, we should not receive any further callbacks.
TEST(ProcessThreadImpl, Deregister) {
  ProcessThreadImpl thread;
  rtc::scoped_ptr<EventWrapper> event(EventWrapper::Create());

  int process_count = 0;
  MockModule module;
  EXPECT_CALL(module, TimeUntilNextProcess()).WillRepeatedly(Return(0));
  EXPECT_CALL(module, Process())
      .WillOnce(DoAll(SetEvent(event.get()),
                      Increment(&process_count),
                      Return(0)))
      .WillRepeatedly(DoAll(Increment(&process_count), Return(0)));

  ASSERT_EQ(0, thread.RegisterModule(&module));
  ASSERT_EQ(0, thread.Start());

  EXPECT_EQ(kEventSignaled, event->Wait(100));
  ASSERT_EQ(0, thread.DeRegisterModule(&module));
  EXPECT_GE(process_count, 1);
  int count_after_deregister = process_count;

  // We shouldn't get any more callbacks.
  EXPECT_EQ(kEventTimeout, event->Wait(20));
  EXPECT_EQ(count_after_deregister, process_count);
  EXPECT_EQ(0, thread.Stop());
}

// Helper function for testing receiving a callback after a certain amount of
// time.  There's some variance of timing built into it to reduce chance of
// flakiness on bots.
void ProcessCallAfterAFewMs(int64_t milliseconds) {
  ProcessThreadImpl thread;
  ASSERT_EQ(0, thread.Start());

  rtc::scoped_ptr<EventWrapper> event(EventWrapper::Create());

  MockModule module;
  int64_t start_time = 0;
  int64_t called_time = 0;
  EXPECT_CALL(module, TimeUntilNextProcess())
      .WillOnce(DoAll(SetTimestamp(&start_time),
                      Return(milliseconds)))
      .WillRepeatedly(Return(milliseconds));
  EXPECT_CALL(module, Process())
      .WillOnce(DoAll(SetTimestamp(&called_time),
                      SetEvent(event.get()),
                      Return(0)))
      .WillRepeatedly(Return(0));

  EXPECT_EQ(0, thread.RegisterModule(&module));

  // Add a buffer of 50ms due to slowness of some trybots
  // (e.g. win_drmemory_light)
  EXPECT_EQ(kEventSignaled, event->Wait(milliseconds + 50));
  ASSERT_EQ(0, thread.Stop());

  ASSERT_GT(start_time, 0);
  ASSERT_GT(called_time, 0);
  // Use >= instead of > since due to rounding and timer accuracy (or lack
  // thereof), can make the test run in "0"ms time.
  EXPECT_GE(called_time, start_time);
  // Check for an acceptable range.
  uint32 diff = called_time - start_time;
  EXPECT_GE(diff, milliseconds - 15);
  EXPECT_LT(diff, milliseconds + 15);
}

TEST(ProcessThreadImpl, ProcessCallAfter5ms) {
  ProcessCallAfterAFewMs(5);
}

TEST(ProcessThreadImpl, ProcessCallAfter50ms) {
  ProcessCallAfterAFewMs(50);
}

TEST(ProcessThreadImpl, ProcessCallAfter200ms) {
  ProcessCallAfterAFewMs(200);
}

// Runs callbacks with the goal of getting up to 50 callbacks within a second
// (on average 1 callback every 20ms).  On real hardware, we're usually pretty
// close to that, but the test bots that run on virtual machines, will
// typically be in the range 30-40 callbacks.
TEST(ProcessThreadImpl, MANUAL_Process50Times) {
  ProcessThreadImpl thread;
  ASSERT_EQ(0, thread.Start());

  rtc::scoped_ptr<EventWrapper> event(EventWrapper::Create());

  MockModule module;
  int callback_count = 0;
  // Ask for a callback after 20ms.
  EXPECT_CALL(module, TimeUntilNextProcess())
      .WillRepeatedly(Return(20));
  EXPECT_CALL(module, Process())
      .WillRepeatedly(DoAll(Increment(&callback_count),
                            Return(0)));

  EXPECT_EQ(0, thread.RegisterModule(&module));

  EXPECT_EQ(kEventTimeout, event->Wait(1000));
  ASSERT_EQ(0, thread.Stop());

  printf("Callback count: %i\n", callback_count);
  // Check that we got called back up to 50 times.
  // Some of the try bots run on slow virtual machines, so the lower bound
  // is much more relaxed to avoid flakiness.
  EXPECT_GE(callback_count, 25);
  EXPECT_LE(callback_count, 50);
}

// Tests that we can wake up the worker thread to give us a callback right
// away when we know the thread is sleeping.
TEST(ProcessThreadImpl, WakeUp) {
  ProcessThreadImpl thread;
  ASSERT_EQ(0, thread.Start());

  rtc::scoped_ptr<EventWrapper> started(EventWrapper::Create());
  rtc::scoped_ptr<EventWrapper> called(EventWrapper::Create());

  MockModule module;
  int64_t start_time = 0;
  int64_t called_time = 0;
  // Ask for a callback after 1000ms first, then 0ms.
  EXPECT_CALL(module, TimeUntilNextProcess())
      .WillOnce(DoAll(SetTimestamp(&start_time),
                      SetEvent(started.get()),
                      Return(1000)))
      .WillRepeatedly(Return(0));
  EXPECT_CALL(module, Process())
      .WillOnce(DoAll(SetTimestamp(&called_time),
                      SetEvent(called.get()),
                      Return(0)))
      .WillRepeatedly(Return(0));

  EXPECT_EQ(0, thread.RegisterModule(&module));

  EXPECT_EQ(kEventSignaled, started->Wait(100));
  thread.WakeUp(&module);
  EXPECT_EQ(kEventSignaled, called->Wait(100));
  ASSERT_EQ(0, thread.Stop());

  ASSERT_GT(start_time, 0);
  ASSERT_GT(called_time, 0);
  EXPECT_GE(called_time, start_time);
  uint32 diff = called_time - start_time;
  // We should have been called back much quicker than 1sec.
  EXPECT_LE(diff, 100u);
}

}  // namespace webrtc
<commit_msg>Disable ProcessThread tests that are dependent on timing. Some of the bots are too slow for the tests to make much sense as they are.<commit_after>/*
 *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "webrtc/modules/interface/module.h"
#include "webrtc/modules/utility/source/process_thread_impl.h"
#include "webrtc/system_wrappers/interface/tick_util.h"

namespace webrtc {

using ::testing::_;
using ::testing::DoAll;
using ::testing::InSequence;
using ::testing::Invoke;
using ::testing::Return;
using ::testing::SetArgPointee;

class MockModule : public Module {
 public:
  MOCK_METHOD0(TimeUntilNextProcess, int64_t());
  MOCK_METHOD0(Process, int32_t());
};

ACTION_P(SetEvent, event) {
  event->Set();
}

ACTION_P(Increment, counter) {
  ++(*counter);
}

ACTION_P(SetTimestamp, ptr) {
  *ptr = TickTime::MillisecondTimestamp();
}

TEST(ProcessThreadImpl, StartStop) {
  ProcessThreadImpl thread;
  EXPECT_EQ(0, thread.Start());
  EXPECT_EQ(0, thread.Stop());
}

TEST(ProcessThreadImpl, MultipleStartStop) {
  ProcessThreadImpl thread;
  for (int i = 0; i < 5; ++i) {
    EXPECT_EQ(0, thread.Start());
    EXPECT_EQ(0, thread.Stop());
  }
}

// Verifies that we get at least call back to Process() on the worker thread.
TEST(ProcessThreadImpl, ProcessCall) {
  ProcessThreadImpl thread;
  ASSERT_EQ(0, thread.Start());

  rtc::scoped_ptr<EventWrapper> event(EventWrapper::Create());

  MockModule module;
  EXPECT_CALL(module, TimeUntilNextProcess()).WillRepeatedly(Return(0));
  EXPECT_CALL(module, Process())
      .WillOnce(DoAll(SetEvent(event.get()), Return(0)))
      .WillRepeatedly(Return(0));

  ASSERT_EQ(0, thread.RegisterModule(&module));
  EXPECT_EQ(kEventSignaled, event->Wait(100));
  EXPECT_EQ(0, thread.Stop());
}

// Same as ProcessCall except the module is registered before the
// call to Start().
TEST(ProcessThreadImpl, ProcessCall2) {
  ProcessThreadImpl thread;
  rtc::scoped_ptr<EventWrapper> event(EventWrapper::Create());

  MockModule module;
  EXPECT_CALL(module, TimeUntilNextProcess()).WillRepeatedly(Return(0));
  EXPECT_CALL(module, Process())
      .WillOnce(DoAll(SetEvent(event.get()), Return(0)))
      .WillRepeatedly(Return(0));

  ASSERT_EQ(0, thread.RegisterModule(&module));
  ASSERT_EQ(thread.Start(), 0);
  EXPECT_EQ(kEventSignaled, event->Wait(100));
  EXPECT_EQ(thread.Stop(), 0);
}

// Tests setting up a module for callbacks and then unregister that module.
// After unregistration, we should not receive any further callbacks.
TEST(ProcessThreadImpl, Deregister) {
  ProcessThreadImpl thread;
  rtc::scoped_ptr<EventWrapper> event(EventWrapper::Create());

  int process_count = 0;
  MockModule module;
  EXPECT_CALL(module, TimeUntilNextProcess()).WillRepeatedly(Return(0));
  EXPECT_CALL(module, Process())
      .WillOnce(DoAll(SetEvent(event.get()),
                      Increment(&process_count),
                      Return(0)))
      .WillRepeatedly(DoAll(Increment(&process_count), Return(0)));

  ASSERT_EQ(0, thread.RegisterModule(&module));
  ASSERT_EQ(0, thread.Start());

  EXPECT_EQ(kEventSignaled, event->Wait(100));
  ASSERT_EQ(0, thread.DeRegisterModule(&module));
  EXPECT_GE(process_count, 1);
  int count_after_deregister = process_count;

  // We shouldn't get any more callbacks.
  EXPECT_EQ(kEventTimeout, event->Wait(20));
  EXPECT_EQ(count_after_deregister, process_count);
  EXPECT_EQ(0, thread.Stop());
}

// Helper function for testing receiving a callback after a certain amount of
// time.  There's some variance of timing built into it to reduce chance of
// flakiness on bots.
void ProcessCallAfterAFewMs(int64_t milliseconds) {
  ProcessThreadImpl thread;
  ASSERT_EQ(0, thread.Start());

  rtc::scoped_ptr<EventWrapper> event(EventWrapper::Create());

  MockModule module;
  int64_t start_time = 0;
  int64_t called_time = 0;
  EXPECT_CALL(module, TimeUntilNextProcess())
      .WillOnce(DoAll(SetTimestamp(&start_time),
                      Return(milliseconds)))
      .WillRepeatedly(Return(milliseconds));
  EXPECT_CALL(module, Process())
      .WillOnce(DoAll(SetTimestamp(&called_time),
                      SetEvent(event.get()),
                      Return(0)))
      .WillRepeatedly(Return(0));

  EXPECT_EQ(0, thread.RegisterModule(&module));

  // Add a buffer of 50ms due to slowness of some trybots
  // (e.g. win_drmemory_light)
  EXPECT_EQ(kEventSignaled, event->Wait(milliseconds + 50));
  ASSERT_EQ(0, thread.Stop());

  ASSERT_GT(start_time, 0);
  ASSERT_GT(called_time, 0);
  // Use >= instead of > since due to rounding and timer accuracy (or lack
  // thereof), can make the test run in "0"ms time.
  EXPECT_GE(called_time, start_time);
  // Check for an acceptable range.
  uint32 diff = called_time - start_time;
  EXPECT_GE(diff, milliseconds - 15);
  EXPECT_LT(diff, milliseconds + 15);
}

// DISABLED for now since the virtual build bots are too slow :(
// TODO(tommi): Fix.
TEST(ProcessThreadImpl, DISABLED_ProcessCallAfter5ms) {
  ProcessCallAfterAFewMs(5);
}

// DISABLED for now since the virtual build bots are too slow :(
// TODO(tommi): Fix.
TEST(ProcessThreadImpl, DISABLED_ProcessCallAfter50ms) {
  ProcessCallAfterAFewMs(50);
}

// DISABLED for now since the virtual build bots are too slow :(
// TODO(tommi): Fix.
TEST(ProcessThreadImpl, DISABLED_ProcessCallAfter200ms) {
  ProcessCallAfterAFewMs(200);
}

// Runs callbacks with the goal of getting up to 50 callbacks within a second
// (on average 1 callback every 20ms).  On real hardware, we're usually pretty
// close to that, but the test bots that run on virtual machines, will
// typically be in the range 30-40 callbacks.
// DISABLED for now since this can take up to 2 seconds to run on the slowest
// build bots.
// TODO(tommi): Fix.
TEST(ProcessThreadImpl, DISABLED_Process50Times) {
  ProcessThreadImpl thread;
  ASSERT_EQ(0, thread.Start());

  rtc::scoped_ptr<EventWrapper> event(EventWrapper::Create());

  MockModule module;
  int callback_count = 0;
  // Ask for a callback after 20ms.
  EXPECT_CALL(module, TimeUntilNextProcess())
      .WillRepeatedly(Return(20));
  EXPECT_CALL(module, Process())
      .WillRepeatedly(DoAll(Increment(&callback_count),
                            Return(0)));

  EXPECT_EQ(0, thread.RegisterModule(&module));

  EXPECT_EQ(kEventTimeout, event->Wait(1000));
  ASSERT_EQ(0, thread.Stop());

  printf("Callback count: %i\n", callback_count);
  // Check that we got called back up to 50 times.
  // Some of the try bots run on slow virtual machines, so the lower bound
  // is much more relaxed to avoid flakiness.
  EXPECT_GE(callback_count, 25);
  EXPECT_LE(callback_count, 50);
}

// Tests that we can wake up the worker thread to give us a callback right
// away when we know the thread is sleeping.
TEST(ProcessThreadImpl, WakeUp) {
  ProcessThreadImpl thread;
  ASSERT_EQ(0, thread.Start());

  rtc::scoped_ptr<EventWrapper> started(EventWrapper::Create());
  rtc::scoped_ptr<EventWrapper> called(EventWrapper::Create());

  MockModule module;
  int64_t start_time = 0;
  int64_t called_time = 0;
  // Ask for a callback after 1000ms first, then 0ms.
  EXPECT_CALL(module, TimeUntilNextProcess())
      .WillOnce(DoAll(SetTimestamp(&start_time),
                      SetEvent(started.get()),
                      Return(1000)))
      .WillRepeatedly(Return(0));
  EXPECT_CALL(module, Process())
      .WillOnce(DoAll(SetTimestamp(&called_time),
                      SetEvent(called.get()),
                      Return(0)))
      .WillRepeatedly(Return(0));

  EXPECT_EQ(0, thread.RegisterModule(&module));

  EXPECT_EQ(kEventSignaled, started->Wait(100));
  thread.WakeUp(&module);
  EXPECT_EQ(kEventSignaled, called->Wait(100));
  ASSERT_EQ(0, thread.Stop());

  ASSERT_GT(start_time, 0);
  ASSERT_GT(called_time, 0);
  EXPECT_GE(called_time, start_time);
  uint32 diff = called_time - start_time;
  // We should have been called back much quicker than 1sec.
  EXPECT_LE(diff, 100u);
}

}  // namespace webrtc
<|endoftext|>


<commit_before>
#include "../../Flare.h"
#include "FlareShipStatus.h"
#include "../../Player/FlareMenuManager.h"

#define LOCTEXT_NAMESPACE "FlareShipStatus"

/*----------------------------------------------------
	Construct
----------------------------------------------------*/

void SFlareShipStatus::Construct(const FArguments& InArgs)
{
	TargetShip = InArgs._Ship;
	const FFlareStyleCatalog& Theme = FFlareStyleSet::GetDefaultTheme();

	ChildSlot
	.VAlign(VAlign_Fill)
	.HAlign(HAlign_Fill)
	.Padding(FMargin(8, 8, 32, 8))
	[
		SNew(SHorizontalBox)

		// Power icon
		+ SHorizontalBox::Slot()
		.AutoWidth()
		[
			SNew(SImage)
			.Image(FFlareStyleSet::GetIcon("Propulsion"))
			.ColorAndOpacity(this, &SFlareShipStatus::GetIconColor, EFlareSubsystem::SYS_Propulsion)
		]

		// RCS icon
		+ SHorizontalBox::Slot()
		.AutoWidth()
		[
			SNew(SImage)
			.Image(FFlareStyleSet::GetIcon("RCS"))
			.ColorAndOpacity(this, &SFlareShipStatus::GetIconColor, EFlareSubsystem::SYS_RCS)
		]

		// Weapon icon
		+ SHorizontalBox::Slot()
		.AutoWidth()
		[
			SAssignNew(WeaponIndicator, SImage)
			.Image(FFlareStyleSet::GetIcon("Shell"))
			.ColorAndOpacity(this, &SFlareShipStatus::GetIconColor, EFlareSubsystem::SYS_Weapon)
		]

		// Health
		+ SHorizontalBox::Slot()
		.AutoWidth()
		[
			SNew(SBox)
			.WidthOverride(50)
			.VAlign(VAlign_Center)
			[
				SNew(SProgressBar)
				.Percent(this, &SFlareShipStatus::GetGlobalHealth)
				.BorderPadding( FVector2D(0,0))
				.Style(&Theme.ProgressBarStyle)
			]
		]
	];

	SetVisibility(EVisibility::Hidden);
}

/*----------------------------------------------------
	Interaction
----------------------------------------------------*/

void SFlareShipStatus::SetTargetShip(UFlareSimulatedSpacecraft* Target)
{
	TargetShip = Target;

	if (TargetShip)
	{
		SetVisibility(EVisibility::Visible);
		if (TargetShip->IsMilitary())
		{
			WeaponIndicator->SetVisibility(EVisibility::Visible);
		}
		else
		{
			WeaponIndicator->SetVisibility(EVisibility::Hidden);
		}
	}
	else
	{
		SetVisibility(EVisibility::Hidden);
	}
}

/*----------------------------------------------------
	Callbacks
----------------------------------------------------*/

void SFlareShipStatus::OnMouseEnter(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent)
{
	SWidget::OnMouseEnter(MyGeometry, MouseEvent);

	AFlareMenuManager* MenuManager = AFlareMenuManager::GetSingleton();
	if (MenuManager && TargetShip)
	{
		FText Info;
		UFlareSimulatedSpacecraftDamageSystem* DamageSystem = TargetShip->GetDamageSystem();

		// Station-specific damage & info
		if (TargetShip->IsStation())
		{
			// Structure
			Info = FText::Format(LOCTEXT("HealthInfoFormat", "Structure : {0}{1}%"),
				Info,
				FText::AsNumber(FMath::RoundToInt(100 * DamageSystem->GetGlobalHealth())));
		}

		// Ship-specific damage
		else
		{
			if (DamageSystem->IsStranded())
			{
				Info = FText::Format(LOCTEXT("ShipStrandedFormat", "{0}This ship is stranded and can't exit the sector !\n"), Info);
			}

			if (DamageSystem->IsUncontrollable())
			{
				Info = FText::Format(LOCTEXT("ShipUncontrollableFormat", "{0}This ship is uncontrollable and can't move in the local space !\n"), Info);
			}

			if (TargetShip->IsMilitary() && DamageSystem->IsDisarmed())
			{
				Info = FText::Format(LOCTEXT("ShipDisarmedFormat", "{0}This ship is disarmed and unable to fight back !\n"), Info);
			}

			// Subsystems
			for (int32 Index = EFlareSubsystem::SYS_None + 1; Index <= EFlareSubsystem::SYS_Weapon; Index++)
			{
				if (Index == EFlareSubsystem::SYS_Weapon && !TargetShip->IsMilitary())
				{
					continue;
				}
				Info = FText::Format(LOCTEXT("HealthInfoFormat", "{0}\n{1} : {2}%"),
					Info,
					UFlareSimulatedSpacecraftDamageSystem::GetSubsystemName((EFlareSubsystem::Type)Index),
					FText::AsNumber(FMath::RoundToInt(100 * DamageSystem->GetSubsystemHealth((EFlareSubsystem::Type)Index, false))));
			}
		}

		MenuManager->ShowTooltip(this, LOCTEXT("Status", "SPACECRAFT STATUS"), Info);
	}
}

void SFlareShipStatus::OnMouseLeave(const FPointerEvent& MouseEvent)
{
	SWidget::OnMouseLeave(MouseEvent);

	AFlareMenuManager* MenuManager = AFlareMenuManager::GetSingleton();
	if (MenuManager)
	{
		MenuManager->HideTooltip(this);
	}
}

TOptional<float> SFlareShipStatus::GetGlobalHealth() const
{
	if (TargetShip)
	{
		return TargetShip->GetDamageSystem()->GetGlobalHealth();
	}
	else
	{
		return 0;
	}
}

FSlateColor SFlareShipStatus::GetIconColor(EFlareSubsystem::Type Type) const
{
	FLinearColor Result = FLinearColor::Black;
	Result.A = 0.0f;

	// Ignore stations
	if (TargetShip && !TargetShip->IsStation())
	{
		bool IsIncapacitated = false;
		UFlareSimulatedSpacecraftDamageSystem* DamageSystem = TargetShip->GetDamageSystem();

		// Only those are used (see above)
		switch (Type)
		{
			case EFlareSubsystem::SYS_Propulsion:    IsIncapacitated = DamageSystem->IsStranded();         break;
			case EFlareSubsystem::SYS_RCS:           IsIncapacitated = DamageSystem->IsUncontrollable();   break;
			case EFlareSubsystem::SYS_Weapon:        IsIncapacitated = DamageSystem->IsDisarmed();         break;
			default: break;
		}

		// Show in red when disabled
		if (IsIncapacitated)
		{
			const FFlareStyleCatalog& Theme = FFlareStyleSet::GetDefaultTheme();
			Result = Theme.DamageColor;
			Result.A = 1.0f;
		}
	}

	return Result;
}

#undef LOCTEXT_NAMESPACE
<commit_msg>#519 Fix spacecraft status format<commit_after>
#include "../../Flare.h"
#include "FlareShipStatus.h"
#include "../../Player/FlareMenuManager.h"

#define LOCTEXT_NAMESPACE "FlareShipStatus"

/*----------------------------------------------------
	Construct
----------------------------------------------------*/

void SFlareShipStatus::Construct(const FArguments& InArgs)
{
	TargetShip = InArgs._Ship;
	const FFlareStyleCatalog& Theme = FFlareStyleSet::GetDefaultTheme();

	ChildSlot
	.VAlign(VAlign_Fill)
	.HAlign(HAlign_Fill)
	.Padding(FMargin(8, 8, 32, 8))
	[
		SNew(SHorizontalBox)

		// Power icon
		+ SHorizontalBox::Slot()
		.AutoWidth()
		[
			SNew(SImage)
			.Image(FFlareStyleSet::GetIcon("Propulsion"))
			.ColorAndOpacity(this, &SFlareShipStatus::GetIconColor, EFlareSubsystem::SYS_Propulsion)
		]

		// RCS icon
		+ SHorizontalBox::Slot()
		.AutoWidth()
		[
			SNew(SImage)
			.Image(FFlareStyleSet::GetIcon("RCS"))
			.ColorAndOpacity(this, &SFlareShipStatus::GetIconColor, EFlareSubsystem::SYS_RCS)
		]

		// Weapon icon
		+ SHorizontalBox::Slot()
		.AutoWidth()
		[
			SAssignNew(WeaponIndicator, SImage)
			.Image(FFlareStyleSet::GetIcon("Shell"))
			.ColorAndOpacity(this, &SFlareShipStatus::GetIconColor, EFlareSubsystem::SYS_Weapon)
		]

		// Health
		+ SHorizontalBox::Slot()
		.AutoWidth()
		[
			SNew(SBox)
			.WidthOverride(50)
			.VAlign(VAlign_Center)
			[
				SNew(SProgressBar)
				.Percent(this, &SFlareShipStatus::GetGlobalHealth)
				.BorderPadding( FVector2D(0,0))
				.Style(&Theme.ProgressBarStyle)
			]
		]
	];

	SetVisibility(EVisibility::Hidden);
}

/*----------------------------------------------------
	Interaction
----------------------------------------------------*/

void SFlareShipStatus::SetTargetShip(UFlareSimulatedSpacecraft* Target)
{
	TargetShip = Target;

	if (TargetShip)
	{
		SetVisibility(EVisibility::Visible);
		if (TargetShip->IsMilitary())
		{
			WeaponIndicator->SetVisibility(EVisibility::Visible);
		}
		else
		{
			WeaponIndicator->SetVisibility(EVisibility::Hidden);
		}
	}
	else
	{
		SetVisibility(EVisibility::Hidden);
	}
}

/*----------------------------------------------------
	Callbacks
----------------------------------------------------*/

void SFlareShipStatus::OnMouseEnter(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent)
{
	SWidget::OnMouseEnter(MyGeometry, MouseEvent);

	AFlareMenuManager* MenuManager = AFlareMenuManager::GetSingleton();
	if (MenuManager && TargetShip)
	{
		FText Info;
		UFlareSimulatedSpacecraftDamageSystem* DamageSystem = TargetShip->GetDamageSystem();

		// Station-specific damage & info
		if (TargetShip->IsStation())
		{
			// Structure
			Info = FText::Format(LOCTEXT("StationHealthInfoFormat", "Structure : {0}%"),
				FText::AsNumber(FMath::RoundToInt(100 * DamageSystem->GetGlobalHealth())));
		}

		// Ship-specific damage
		else
		{
			if (DamageSystem->IsStranded())
			{
				Info = FText::Format(LOCTEXT("ShipStrandedFormat", "{0}This ship is stranded and can't exit the sector !\n"), Info);
			}

			if (DamageSystem->IsUncontrollable())
			{
				Info = FText::Format(LOCTEXT("ShipUncontrollableFormat", "{0}This ship is uncontrollable and can't move in the local space !\n"), Info);
			}

			if (TargetShip->IsMilitary() && DamageSystem->IsDisarmed())
			{
				Info = FText::Format(LOCTEXT("ShipDisarmedFormat", "{0}This ship is disarmed and unable to fight back !\n"), Info);
			}

			// Subsystems
			for (int32 Index = EFlareSubsystem::SYS_None + 1; Index <= EFlareSubsystem::SYS_Weapon; Index++)
			{
				if (Index == EFlareSubsystem::SYS_Weapon && !TargetShip->IsMilitary())
				{
					continue;
				}
				Info = FText::Format(LOCTEXT("ShipHealthInfoFormat", "{0}\n{1} : {2}%"),
					Info,
					UFlareSimulatedSpacecraftDamageSystem::GetSubsystemName((EFlareSubsystem::Type)Index),
					FText::AsNumber(FMath::RoundToInt(100 * DamageSystem->GetSubsystemHealth((EFlareSubsystem::Type)Index, false))));
			}
		}

		MenuManager->ShowTooltip(this, LOCTEXT("Status", "SPACECRAFT STATUS"), Info);
	}
}

void SFlareShipStatus::OnMouseLeave(const FPointerEvent& MouseEvent)
{
	SWidget::OnMouseLeave(MouseEvent);

	AFlareMenuManager* MenuManager = AFlareMenuManager::GetSingleton();
	if (MenuManager)
	{
		MenuManager->HideTooltip(this);
	}
}

TOptional<float> SFlareShipStatus::GetGlobalHealth() const
{
	if (TargetShip)
	{
		return TargetShip->GetDamageSystem()->GetGlobalHealth();
	}
	else
	{
		return 0;
	}
}

FSlateColor SFlareShipStatus::GetIconColor(EFlareSubsystem::Type Type) const
{
	FLinearColor Result = FLinearColor::Black;
	Result.A = 0.0f;

	// Ignore stations
	if (TargetShip && !TargetShip->IsStation())
	{
		bool IsIncapacitated = false;
		UFlareSimulatedSpacecraftDamageSystem* DamageSystem = TargetShip->GetDamageSystem();

		// Only those are used (see above)
		switch (Type)
		{
			case EFlareSubsystem::SYS_Propulsion:    IsIncapacitated = DamageSystem->IsStranded();         break;
			case EFlareSubsystem::SYS_RCS:           IsIncapacitated = DamageSystem->IsUncontrollable();   break;
			case EFlareSubsystem::SYS_Weapon:        IsIncapacitated = DamageSystem->IsDisarmed();         break;
			default: break;
		}

		// Show in red when disabled
		if (IsIncapacitated)
		{
			const FFlareStyleCatalog& Theme = FFlareStyleSet::GetDefaultTheme();
			Result = Theme.DamageColor;
			Result.A = 1.0f;
		}
	}

	return Result;
}

#undef LOCTEXT_NAMESPACE
<|endoftext|>


<commit_before>#include "JPetParamManager.h"

#include <TFile.h>
#include <boost/property_tree/xml_parser.hpp>

using namespace std;

JPetParamManager::JPetParamManager():
  fBank(0)
{
  /* */
}

JPetParamManager::~JPetParamManager()
{
  if (fBank) {
    delete fBank;
    fBank = 0;
  }
}

/// @param DBConfigFile configuration file with the database connection settings
JPetParamManager::JPetParamManager(const char* dBConfigFile):
  fDBParamGetter(dBConfigFile),
  fBank(0)
{
}

void JPetParamManager::getParametersFromDatabase(const int run)
{
  if (fBank) {
    delete fBank;
    fBank = 0;
  }
  fBank = fDBParamGetter.generateParamBank(run);
}

bool JPetParamManager::saveParametersToFile(const char* filename)
{
  TFile file(filename, "UPDATE");
  if (!file.IsOpen()) {
    ERROR("Could not write to file.");
    return false;
  }
  file.cd();
  file.WriteObject(fBank, "ParamBank");
  return true;
}

bool JPetParamManager::saveParametersToFile(JPetWriter * writer)
{
  if (!writer->isOpen()) {
    ERROR("Could not write parameters to file. The provided JPetWriter is closed.");
    return false;
  }
  writer->writeObject(fBank, "ParamBank");
  return true;
}

bool JPetParamManager::readParametersFromFile(JPetReader * reader)
{
  if (!reader->isOpen()) {
    ERROR("Cannot read parameters from file. The provided JPetReader is closed.");
    return false;
  }
  fBank = static_cast<JPetParamBank*>(reader->getObject("ParamBank"));

  if (!fBank) return false;
  return true;
}

bool JPetParamManager::readParametersFromFile(const char* filename)
{
  TFile file(filename, "READ");
  if (!file.IsOpen()) {
    ERROR("Could not read from file.");
    return false;
  }
  fBank = static_cast<JPetParamBank*>(file.Get("ParamBank"));

  if (!fBank) return false;
  return true;
}

void JPetParamManager::clearParameters()
{
  assert(fBank);
  fBank->clear();
}

void JPetParamManager::createXMLFile(const std::string &channelDataFileName, int channelOffset, int numberOfChannels)
{
  using boost::property_tree::ptree;
  ptree pt;

  std::string debug = "OFF";
  std::string dataSourceType = "TRB3_S";
  std::string dataSourceTrbNetAddress = "8000";
  std::string dataSourceHubAddress = "8000";
  std::string dataSourceReferenceChannel = "0";
  std::string dataSourceCorrectionFile = "raw";

  pt.put("READOUT.DEBUG", debug);
  pt.put("READOUT.DATA_SOURCE.TYPE", dataSourceType);
  pt.put("READOUT.DATA_SOURCE.TRBNET_ADDRESS", dataSourceTrbNetAddress);
  pt.put("READOUT.DATA_SOURCE.HUB_ADDRESS", dataSourceHubAddress);
  pt.put("READOUT.DATA_SOURCE.REFERENCE_CHANNEL", dataSourceReferenceChannel);
  pt.put("READOUT.DATA_SOURCE.CORRECTION_FILE", dataSourceCorrectionFile);

  ptree &externalNode = pt.add("READOUT.DATA_SOURCE.MODULES", "");

  ptree &internalNode = externalNode.add("MODULE", "");
  internalNode.put("TYPE", "LATTICE_TDC");
  internalNode.put("TRBNET_ADDRESS", "e000");
  internalNode.put("NUMBER_OF_CHANNELS", numberOfChannels);
  internalNode.put("CHANNEL_OFFSET", channelOffset);
  internalNode.put("RESOLUTION", "100");
  internalNode.put("MEASUREMENT_TYPE", "TDC");

  write_xml(channelDataFileName, pt);
}

void JPetParamManager::getTOMBDataAndCreateXMLFile(const int p_run_id)
{
  fDBParamGetter.fillTOMBChannels(p_run_id, *fBank);//private (add friend)
  int TOMBChannelsSize = fBank->getTOMBChannelsSize();
  int channelOffset = 0;
  int numberOfChannels = 0;

  if(TOMBChannelsSize)
  {
    for(unsigned int i=0;i<TOMBChannelsSize;++i)
    {
      if(i==0)
      {
	std::string description = fBank->getTOMBChannel(i).getDescription();
	channelOffset = fDBParamGetter.getTOMBChannelFromDescription(description);//private (add friend)
      }
      ++numberOfChannels;
    }
    createXMLFile("out.xml", channelOffset, numberOfChannels);
    return;
  }
  ERROR("TOMBChannelsSize is equal to zero.");
}
<commit_msg>Change xml configuration file name.<commit_after>#include "JPetParamManager.h"

#include <TFile.h>
#include <boost/property_tree/xml_parser.hpp>

using namespace std;

JPetParamManager::JPetParamManager():
  fBank(0)
{
  /* */
}

JPetParamManager::~JPetParamManager()
{
  if (fBank) {
    delete fBank;
    fBank = 0;
  }
}

/// @param DBConfigFile configuration file with the database connection settings
JPetParamManager::JPetParamManager(const char* dBConfigFile):
  fDBParamGetter(dBConfigFile),
  fBank(0)
{
}

void JPetParamManager::getParametersFromDatabase(const int run)
{
  if (fBank) {
    delete fBank;
    fBank = 0;
  }
  fBank = fDBParamGetter.generateParamBank(run);
}

bool JPetParamManager::saveParametersToFile(const char* filename)
{
  TFile file(filename, "UPDATE");
  if (!file.IsOpen()) {
    ERROR("Could not write to file.");
    return false;
  }
  file.cd();
  file.WriteObject(fBank, "ParamBank");
  return true;
}

bool JPetParamManager::saveParametersToFile(JPetWriter * writer)
{
  if (!writer->isOpen()) {
    ERROR("Could not write parameters to file. The provided JPetWriter is closed.");
    return false;
  }
  writer->writeObject(fBank, "ParamBank");
  return true;
}

bool JPetParamManager::readParametersFromFile(JPetReader * reader)
{
  if (!reader->isOpen()) {
    ERROR("Cannot read parameters from file. The provided JPetReader is closed.");
    return false;
  }
  fBank = static_cast<JPetParamBank*>(reader->getObject("ParamBank"));

  if (!fBank) return false;
  return true;
}

bool JPetParamManager::readParametersFromFile(const char* filename)
{
  TFile file(filename, "READ");
  if (!file.IsOpen()) {
    ERROR("Could not read from file.");
    return false;
  }
  fBank = static_cast<JPetParamBank*>(file.Get("ParamBank"));

  if (!fBank) return false;
  return true;
}

void JPetParamManager::clearParameters()
{
  assert(fBank);
  fBank->clear();
}

void JPetParamManager::createXMLFile(const std::string &channelDataFileName, int channelOffset, int numberOfChannels)
{
  using boost::property_tree::ptree;
  ptree pt;

  std::string debug = "OFF";
  std::string dataSourceType = "TRB3_S";
  std::string dataSourceTrbNetAddress = "8000";
  std::string dataSourceHubAddress = "8000";
  std::string dataSourceReferenceChannel = "0";
  std::string dataSourceCorrectionFile = "raw";

  pt.put("READOUT.DEBUG", debug);
  pt.put("READOUT.DATA_SOURCE.TYPE", dataSourceType);
  pt.put("READOUT.DATA_SOURCE.TRBNET_ADDRESS", dataSourceTrbNetAddress);
  pt.put("READOUT.DATA_SOURCE.HUB_ADDRESS", dataSourceHubAddress);
  pt.put("READOUT.DATA_SOURCE.REFERENCE_CHANNEL", dataSourceReferenceChannel);
  pt.put("READOUT.DATA_SOURCE.CORRECTION_FILE", dataSourceCorrectionFile);

  ptree &externalNode = pt.add("READOUT.DATA_SOURCE.MODULES", "");

  ptree &internalNode = externalNode.add("MODULE", "");
  internalNode.put("TYPE", "LATTICE_TDC");
  internalNode.put("TRBNET_ADDRESS", "e000");
  internalNode.put("NUMBER_OF_CHANNELS", numberOfChannels);
  internalNode.put("CHANNEL_OFFSET", channelOffset);
  internalNode.put("RESOLUTION", "100");
  internalNode.put("MEASUREMENT_TYPE", "TDC");

  write_xml(channelDataFileName, pt);
}

void JPetParamManager::getTOMBDataAndCreateXMLFile(const int p_run_id)
{
  fDBParamGetter.fillTOMBChannels(p_run_id, *fBank);//private (add friend)
  int TOMBChannelsSize = fBank->getTOMBChannelsSize();
  int channelOffset = 0;
  int numberOfChannels = 0;

  if(TOMBChannelsSize)
  {
    for(unsigned int i=0;i<TOMBChannelsSize;++i)
    {
      if(i==0)
      {
	std::string description = fBank->getTOMBChannel(i).getDescription();
	channelOffset = fDBParamGetter.getTOMBChannelFromDescription(description);//private (add friend)
      }
      ++numberOfChannels;
    }
    createXMLFile("conf.xml", channelOffset, numberOfChannels);
    return;
  }
  ERROR("TOMBChannelsSize is equal to zero.");
}
<|endoftext|>