<commit_before>/*
 * Copyright 2002-2005 The Apache Software Foundation.
 *
 * 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.
 */

/*
 * XSEC
 *
 * XSECCryptoSymmetricKey := Bulk encryption algorithms should all be
 *							implemented via this interface
 *
 * Author(s): Berin Lautenbach
 *
 * $Id$
 *
 */

#ifndef WINCAPICRYPTOSYMMETRICKEY_INCLUDE
#define WINCAPICRYPTOSYMMETRICKEY_INCLUDE

#include <xsec/framework/XSECDefs.hpp>
#include <xsec/enc/XSECCryptoSymmetricKey.hpp>

#if defined (HAVE_WINCAPI)

#if !defined(_WIN32_WINNT)
#	define _WIN32_WINNT 0x0400
#endif

#include <wincrypt.h>

#define WINCAPI_MAX_BLOCK_SIZE		32

/**
 * \ingroup wincapicrypto
 * @{
 */

/**
 * \brief Base interface definition for symmetric key material.
 *
 * This is the implementation for a wrapper of Windows CryptoAPI symmetric
 * crypto functions.
 */

class DSIG_EXPORT WinCAPICryptoSymmetricKey : public XSECCryptoSymmetricKey {

public :

	/** @name Constructors and Destructors */
	//@{

	/**
	 * \brief Constructor
	 *
	 * Can only construct a Symmetric key if we know what type it is
	 *
	 * @param prov The appropriate provider that supports the required algorithm.
	 * Can be 0 if the app is going to pass in an octet via setKey, as the library
	 * will use its own internal key store and handle to CSP.
	 * @param type The type of key (i.e. algorithm) to create
	 **/

	WinCAPICryptoSymmetricKey(HCRYPTPROV prov, XSECCryptoSymmetricKey::SymmetricKeyType type);

	/**
	 * \brief Destructor
	 *
	 * Implementations must ensure that the held key is properly destroyed
	 * (overwritten) when key objects are deleted.
	 */

	virtual ~WinCAPICryptoSymmetricKey();

	//@}

	/** @name Basic CryptoKey Interface methods */
	//@{

	/**
	 * \brief Returns a string that identifies the crypto owner of this library.
	 */

	virtual const XMLCh * getProviderName();

	/**
	 * \brief Clone the key
	 *
	 * All keys need to be able to copy themselves and return
	 * a pointer to the copy.  This allows the library to
	 * duplicate keys.
	 */

	virtual XSECCryptoKey * clone();

	//@}

	/** @name Symmetric key interface methods */
	//@{

	/**
	 * \brief What type of symmetric key is this?
	 *
	 * There are a number of different types of symmetric key.
	 * This method allows callers to determine the type of this
	 * particular key
	 */

	SymmetricKeyType getSymmetricKeyType(void);

	/**
	 * \brief Set the key from the provided bytes
	 *
	 * Symmetric keys can all be loaded from a buffer containing a series
	 * of bytes.
	 *
	 * @param key The buffer containing the key bytes
	 * @param keyLen The number of key bytes in the buffer
	 *
	 */

	void setKey(const unsigned char * key, unsigned int keyLen);

	/**
	 * \brief Initialise an decryption process
	 *
	 * Setup the key to get ready for a decryption session.
	 * Callers can pass in an IV.  If one is not provided,
	 * but the algorithm requires one (e.g. 3DES_CBC), then
	 * implementations should assume that the start of the
	 * cipher text stream will in fact be the IV.
	 *
	 * @param doPad By default, we perform padding for last block
	 * @param mode mode selection (Currently ECB or CBC mode only)
	 * @param iv Initialisation Vector to be used.  NULL if one is
	 * not required, or if IV will be set from data stream
	 * @returns true if the initialisation succeeded.
	 */

	virtual bool decryptInit(bool doPad = true,
							 SymmetricKeyMode mode = MODE_CBC,
							 const unsigned char * iv = NULL);

	/**
	 * \brief Continue an decrypt operation using this key.
	 *
	 * Decryption must have been set up using an encryptInit
	 * call.  Takes the inBuf and continues a decryption operation,
	 * writing the output to outBuf.
	 *
	 * This function does not have to guarantee that all input
	 * will be decrypted.  In cases where the input is not a length
	 * of the block size, the implementation will need to hold back
	 * cipher-text to be handles during the next operation.
	 *
	 * @note While maxOutLength is defined, the OpenSSL libraries will
	 * not read the value, so the onus is on the caller to ensure the
	 * buffer is long enough to hold the output!
	 *
	 * @param inBuf Octets to be decrypted
	 * @param plainBuf Buffer to place output in
	 * @param inLength Number of bytes to decrypt
	 * @param maxOutLength Maximum number of bytes to place in output
	 * buffer
	 * @returns Bytes placed in output Buffer
	 */

	virtual unsigned int decrypt(const unsigned char * inBuf,
								 unsigned char * plainBuf,
								 unsigned int inLength,
								 unsigned int maxOutLength);

	/**
	 * \brief Finish a decryption operation
	 *
	 * Complete a decryption process.  No cipher text is passed in,
	 * as this should simply be removing any remaining text from
	 * the plain storage buffer.
	 *
	 * May throw an exception if there is some stored cipher text
	 * that is not the length of the block size for block algorithms.
	 *
	 * @note While maxOutLength is defined, the OpenSSL libraries will
	 * not read the value, so the onus is on the caller to ensure the
	 * buffer is long enough to hold the output!
	 *
	 * @param plainBuf Buffer to place any remaining plain text in
	 * @param maxOutLength Maximum number of bytes to pace in output
	 * @returns Bytes placed in output buffer
	 */

	virtual unsigned int decryptFinish(unsigned char * plainBuf,
									   unsigned int maxOutLength);

	/**
	 * \brief Initialise an encryption process
	 *
	 * Setup the key to get ready for a decryption session.
	 * Callers can pass in an IV.  If one is not provided,
	 * but the algorithm requires one (e.g. 3DES_CBC), then
	 * implementations are required to generate one.
	 *
	 * @param doPad By default, we perform padding for last block
	 * @param mode What mode to handle blocks (Currently CBC or ECB)
	 * @param iv Initialisation Vector to be used.  NULL if one is
	 * not required, or if IV is to be generated
	 * @returns true if the initialisation succeeded.
	 */

	virtual bool encryptInit(bool doPad = true,
							 SymmetricKeyMode mode = MODE_CBC,
							 const unsigned char * iv = NULL);

	/**
	 * \brief Continue an encryption operation using this key.
	 *
	 * Encryption must have been set up using an encryptInit
	 * call.  Takes the inBuf and continues a encryption operation,
	 * writing the output to outBuf.
	 *
	 * This function does not have to guarantee that all input
	 * will be encrypted.  In cases where the input is not a length
	 * of the block size, the implementation will need to hold back
	 * plain-text to be handled during the next operation.
	 *
	 * @param inBuf Octets to be encrypted
	 * @param cipherBuf Buffer to place output in
	 * @param inLength Number of bytes to encrypt
	 * @param maxOutLength Maximum number of bytes to place in output
	 * buffer
	 * @returns Bytes placed in output Buffer
	 */

	virtual unsigned int encrypt(const unsigned char * inBuf,
								 unsigned char * cipherBuf,
								 unsigned int inLength,
								 unsigned int maxOutLength);

	/**
	 * \brief Finish a encryption operation
	 *
	 * Complete a encryption process.  No plain text is passed in,
	 * as this should simply be removing any remaining text from
	 * the plain storage buffer and creating a final padded block.
	 *
	 * Padding is performed by taking the remaining block, and
	 * setting the last byte to equal the number of bytes of
	 * padding.  If the plain was an exact multiple of the block size,
	 * then an extra block of padding will be used.  For example, if
	 * the block size is 8 bytes, and there were three remaining plain
	 * text bytes (0x01, 0x02 and 0x03), the final block will be :
	 *
	 * 0x010203????????05
	 *
	 * @param cipherBuf Buffer to place final block of cipher text in
	 * @param maxOutLength Maximum number of bytes to pace in output
	 * @returns Bytes placed in output buffer
	 */

	virtual unsigned int encryptFinish(unsigned char * plainBuf,
									   unsigned int maxOutLength);

	//@}

	/** @name Windows utility functions */
	//@{

	/**
	 * \brief Create a symmetric key from a octet string
	 *
	 * Uses the ApacheKeyStore to wrap an octet string in a public key
	 * and then load it into the Apache Key Container within the defined
	 * CSP
	 *
	 * @param key The buffer of bytes to load from
	 * @param keyLen The number of bytes to load
	 * @param type The key type to create from the bytes
	 * @param prov If NULL, ignored.  If non-null, but *prov == 0, the
	 * function will use an internal handle to a CSP and return the value
	 * in *prov.  If *prov != 0, use contents of *prov as the provider to
	 * load the key into.  NOTE - The provider must have a
	 * AT_KEYEXCHANGE key pair available.
	 * @returns a pointer to the key or 0 on failure
	 */

	static HCRYPTKEY createWindowsKey(const unsigned char * key,
									  unsigned int keyLen,
									  XSECCryptoSymmetricKey::SymmetricKeyType type,
									  HCRYPTPROV * prov);

private:

	// Unimplemented constructors

	WinCAPICryptoSymmetricKey();
	WinCAPICryptoSymmetricKey(const WinCAPICryptoSymmetricKey &);
	WinCAPICryptoSymmetricKey & operator= (const WinCAPICryptoSymmetricKey &);

	int decryptCtxInit(const unsigned char * iv);
	void encryptCtxInit(const unsigned char * iv);

	// Private variables
	SymmetricKeyType				m_keyType;
	SymmetricKeyMode				m_keyMode;		// ECB or CBC
	safeBuffer						m_keyBuf;		// Holder of the key
	unsigned int					m_keyLen;
	bool							m_initialised;
	bool							m_doPad;

	unsigned char					m_lastBlock[WINCAPI_MAX_BLOCK_SIZE];
	unsigned int					m_bytesInLastBlock;
	unsigned int					m_blockSize;
	unsigned int					m_ivSize;

	HCRYPTPROV						m_p;
	HCRYPTKEY						m_k;

};

#endif /* HAVE_WINCAPI */
#endif /* WINCAPICRYPTOSYMMETRICKEY_INCLUDE */
<commit_msg>Minor typo fix.<commit_after>/*
 * Copyright 2002-2005 The Apache Software Foundation.
 *
 * 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.
 */

/*
 * XSEC
 *
 * XSECCryptoSymmetricKey := Bulk encryption algorithms should all be
 *							implemented via this interface
 *
 * Author(s): Berin Lautenbach
 *
 * $Id$
 *
 */

#ifndef WINCAPICRYPTOSYMMETRICKEY_INCLUDE
#define WINCAPICRYPTOSYMMETRICKEY_INCLUDE

#include <xsec/framework/XSECDefs.hpp>
#include <xsec/enc/XSECCryptoSymmetricKey.hpp>

#if defined (HAVE_WINCAPI)

#if !defined(_WIN32_WINNT)
#	define _WIN32_WINNT 0x0400
#endif

#include <wincrypt.h>

#define WINCAPI_MAX_BLOCK_SIZE		32

/**
 * \ingroup wincapicrypto
 * @{
 */

/**
 * \brief Base interface definition for symmetric key material.
 *
 * This is the implementation for a wrapper of Windows CryptoAPI symmetric
 * crypto functions.
 */

class DSIG_EXPORT WinCAPICryptoSymmetricKey : public XSECCryptoSymmetricKey {

public :

	/** @name Constructors and Destructors */
	//@{

	/**
	 * \brief Constructor
	 *
	 * Can only construct a Symmetric key if we know what type it is
	 *
	 * @param prov The appropriate provider that supports the required algorithm.
	 * Can be 0 if the app is going to pass in an octet via setKey, as the library
	 * will use its own internal key store and handle to CSP.
	 * @param type The type of key (i.e. algorithm) to create
	 **/

	WinCAPICryptoSymmetricKey(HCRYPTPROV prov, XSECCryptoSymmetricKey::SymmetricKeyType type);

	/**
	 * \brief Destructor
	 *
	 * Implementations must ensure that the held key is properly destroyed
	 * (overwritten) when key objects are deleted.
	 */

	virtual ~WinCAPICryptoSymmetricKey();

	//@}

	/** @name Basic CryptoKey Interface methods */
	//@{

	/**
	 * \brief Returns a string that identifies the crypto owner of this library.
	 */

	virtual const XMLCh * getProviderName();

	/**
	 * \brief Clone the key
	 *
	 * All keys need to be able to copy themselves and return
	 * a pointer to the copy.  This allows the library to
	 * duplicate keys.
	 */

	virtual XSECCryptoKey * clone();

	//@}

	/** @name Symmetric key interface methods */
	//@{

	/**
	 * \brief What type of symmetric key is this?
	 *
	 * There are a number of different types of symmetric key.
	 * This method allows callers to determine the type of this
	 * particular key
	 */

	SymmetricKeyType getSymmetricKeyType(void);

	/**
	 * \brief Set the key from the provided bytes
	 *
	 * Symmetric keys can all be loaded from a buffer containing a series
	 * of bytes.
	 *
	 * @param key The buffer containing the key bytes
	 * @param keyLen The number of key bytes in the buffer
	 *
	 */

	void setKey(const unsigned char * key, unsigned int keyLen);

	/**
	 * \brief Initialise an decryption process
	 *
	 * Setup the key to get ready for a decryption session.
	 * Callers can pass in an IV.  If one is not provided,
	 * but the algorithm requires one (e.g. 3DES_CBC), then
	 * implementations should assume that the start of the
	 * cipher text stream will in fact be the IV.
	 *
	 * @param doPad By default, we perform padding for last block
	 * @param mode mode selection (Currently ECB or CBC mode only)
	 * @param iv Initialisation Vector to be used.  NULL if one is
	 * not required, or if IV will be set from data stream
	 * @returns true if the initialisation succeeded.
	 */

	virtual bool decryptInit(bool doPad = true,
							 SymmetricKeyMode mode = MODE_CBC,
							 const unsigned char * iv = NULL);

	/**
	 * \brief Continue an decrypt operation using this key.
	 *
	 * Decryption must have been set up using an encryptInit
	 * call.  Takes the inBuf and continues a decryption operation,
	 * writing the output to outBuf.
	 *
	 * This function does not have to guarantee that all input
	 * will be decrypted.  In cases where the input is not a length
	 * of the block size, the implementation will need to hold back
	 * cipher-text to be handles during the next operation.
	 *
	 * @note While maxOutLength is defined, the WinCAPI library will
	 * not read the value, so the onus is on the caller to ensure the
	 * buffer is long enough to hold the output!
	 *
	 * @param inBuf Octets to be decrypted
	 * @param plainBuf Buffer to place output in
	 * @param inLength Number of bytes to decrypt
	 * @param maxOutLength Maximum number of bytes to place in output
	 * buffer
	 * @returns Bytes placed in output Buffer
	 */

	virtual unsigned int decrypt(const unsigned char * inBuf,
								 unsigned char * plainBuf,
								 unsigned int inLength,
								 unsigned int maxOutLength);

	/**
	 * \brief Finish a decryption operation
	 *
	 * Complete a decryption process.  No cipher text is passed in,
	 * as this should simply be removing any remaining text from
	 * the plain storage buffer.
	 *
	 * May throw an exception if there is some stored cipher text
	 * that is not the length of the block size for block algorithms.
	 *
	 * @note While maxOutLength is defined, the WinCAPI library will
	 * not read the value, so the onus is on the caller to ensure the
	 * buffer is long enough to hold the output!
	 *
	 * @param plainBuf Buffer to place any remaining plain text in
	 * @param maxOutLength Maximum number of bytes to pace in output
	 * @returns Bytes placed in output buffer
	 */

	virtual unsigned int decryptFinish(unsigned char * plainBuf,
									   unsigned int maxOutLength);

	/**
	 * \brief Initialise an encryption process
	 *
	 * Setup the key to get ready for a decryption session.
	 * Callers can pass in an IV.  If one is not provided,
	 * but the algorithm requires one (e.g. 3DES_CBC), then
	 * implementations are required to generate one.
	 *
	 * @param doPad By default, we perform padding for last block
	 * @param mode What mode to handle blocks (Currently CBC or ECB)
	 * @param iv Initialisation Vector to be used.  NULL if one is
	 * not required, or if IV is to be generated
	 * @returns true if the initialisation succeeded.
	 */

	virtual bool encryptInit(bool doPad = true,
							 SymmetricKeyMode mode = MODE_CBC,
							 const unsigned char * iv = NULL);

	/**
	 * \brief Continue an encryption operation using this key.
	 *
	 * Encryption must have been set up using an encryptInit
	 * call.  Takes the inBuf and continues a encryption operation,
	 * writing the output to outBuf.
	 *
	 * This function does not have to guarantee that all input
	 * will be encrypted.  In cases where the input is not a length
	 * of the block size, the implementation will need to hold back
	 * plain-text to be handled during the next operation.
	 *
	 * @param inBuf Octets to be encrypted
	 * @param cipherBuf Buffer to place output in
	 * @param inLength Number of bytes to encrypt
	 * @param maxOutLength Maximum number of bytes to place in output
	 * buffer
	 * @returns Bytes placed in output Buffer
	 */

	virtual unsigned int encrypt(const unsigned char * inBuf,
								 unsigned char * cipherBuf,
								 unsigned int inLength,
								 unsigned int maxOutLength);

	/**
	 * \brief Finish a encryption operation
	 *
	 * Complete a encryption process.  No plain text is passed in,
	 * as this should simply be removing any remaining text from
	 * the plain storage buffer and creating a final padded block.
	 *
	 * Padding is performed by taking the remaining block, and
	 * setting the last byte to equal the number of bytes of
	 * padding.  If the plain was an exact multiple of the block size,
	 * then an extra block of padding will be used.  For example, if
	 * the block size is 8 bytes, and there were three remaining plain
	 * text bytes (0x01, 0x02 and 0x03), the final block will be :
	 *
	 * 0x010203????????05
	 *
	 * @param cipherBuf Buffer to place final block of cipher text in
	 * @param maxOutLength Maximum number of bytes to pace in output
	 * @returns Bytes placed in output buffer
	 */

	virtual unsigned int encryptFinish(unsigned char * plainBuf,
									   unsigned int maxOutLength);

	//@}

	/** @name Windows utility functions */
	//@{

	/**
	 * \brief Create a symmetric key from a octet string
	 *
	 * Uses the ApacheKeyStore to wrap an octet string in a public key
	 * and then load it into the Apache Key Container within the defined
	 * CSP
	 *
	 * @param key The buffer of bytes to load from
	 * @param keyLen The number of bytes to load
	 * @param type The key type to create from the bytes
	 * @param prov If NULL, ignored.  If non-null, but *prov == 0, the
	 * function will use an internal handle to a CSP and return the value
	 * in *prov.  If *prov != 0, use contents of *prov as the provider to
	 * load the key into.  NOTE - The provider must have a
	 * AT_KEYEXCHANGE key pair available.
	 * @returns a pointer to the key or 0 on failure
	 */

	static HCRYPTKEY createWindowsKey(const unsigned char * key,
									  unsigned int keyLen,
									  XSECCryptoSymmetricKey::SymmetricKeyType type,
									  HCRYPTPROV * prov);

private:

	// Unimplemented constructors

	WinCAPICryptoSymmetricKey();
	WinCAPICryptoSymmetricKey(const WinCAPICryptoSymmetricKey &);
	WinCAPICryptoSymmetricKey & operator= (const WinCAPICryptoSymmetricKey &);

	int decryptCtxInit(const unsigned char * iv);
	void encryptCtxInit(const unsigned char * iv);

	// Private variables
	SymmetricKeyType				m_keyType;
	SymmetricKeyMode				m_keyMode;		// ECB or CBC
	safeBuffer						m_keyBuf;		// Holder of the key
	unsigned int					m_keyLen;
	bool							m_initialised;
	bool							m_doPad;

	unsigned char					m_lastBlock[WINCAPI_MAX_BLOCK_SIZE];
	unsigned int					m_bytesInLastBlock;
	unsigned int					m_blockSize;
	unsigned int					m_ivSize;

	HCRYPTPROV						m_p;
	HCRYPTKEY						m_k;

};

#endif /* HAVE_WINCAPI */
#endif /* WINCAPICRYPTOSYMMETRICKEY_INCLUDE */
<|endoftext|>


<commit_before>/* Copyright 2015 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#include "tensorflow/core/common_runtime/rendezvous_mgr.h"

#include <unordered_set>

#include "tensorflow/core/common_runtime/copy_tensor.h"
#include "tensorflow/core/common_runtime/device.h"
#include "tensorflow/core/common_runtime/device_mgr.h"
#include "tensorflow/core/framework/types.h"
#include "tensorflow/core/lib/core/errors.h"
#include "tensorflow/core/lib/core/notification.h"
#include "tensorflow/core/lib/strings/numbers.h"
#include "tensorflow/core/lib/strings/str_util.h"
#include "tensorflow/core/platform/logging.h"
#include "tensorflow/core/platform/mutex.h"
#include "tensorflow/core/platform/types.h"

namespace tensorflow {

IntraProcessRendezvous::IntraProcessRendezvous(const DeviceMgr* device_mgr)
    : device_mgr_(device_mgr), local_(NewLocalRendezvous()) {}

IntraProcessRendezvous::~IntraProcessRendezvous() { local_->Unref(); }

Status IntraProcessRendezvous::Send(const ParsedKey& parsed,
                                    const Rendezvous::Args& args,
                                    const Tensor& val, const bool is_dead) {
  VLOG(1) << "IntraProcessRendezvous Send " << this << " " << parsed.FullKey();
  {
    mutex_lock l(mu_);
    if (!status_.ok()) return status_;
  }

  // Buffers "val" and "device_context" in local_.
  return local_->Send(parsed, args, val, is_dead);
}

Status IntraProcessRendezvous::ParseKey(const string& key, bool is_src,
                                        Rendezvous::ParsedKey* parsed) {
  {
    mutex_lock l(mu_);
    if (!status_.ok()) return status_;
  }
  TF_RETURN_IF_ERROR(Rendezvous::ParseKey(key, parsed));
  return Status::OK();
}

void IntraProcessRendezvous::SameWorkerRecvDone(
    const Rendezvous::ParsedKey& parsed, const Rendezvous::Args& send_args,
    const Rendezvous::Args& recv_args, const Tensor& in, Tensor* out,
    StatusCallback done) {
  // Do a quick copy (sharing the underlying buffer) if both tensors
  // are on host memory.
  const bool src_host =
      (send_args.alloc_attrs.on_host() || parsed.src.type == "CPU");
  const bool dst_host =
      (recv_args.alloc_attrs.on_host() || parsed.dst.type == "CPU");
  if (src_host && dst_host) {
    *out = in;
    done(Status::OK());
    return;
  }

  // This copy must involve a non-CPU device. Hence, "in" must support DMA
  // (e.g., string tensors do not work on GPU).  Variant copy DMA
  // checks happen inside CopyTensor::ViaDMA.
  if (!DataTypeCanUseMemcpy(in.dtype()) && in.dtype() != DT_VARIANT) {
    done(errors::InvalidArgument("Non-DMA-safe ", DataTypeString(in.dtype()),
                                 " tensor may not be copied from/to a GPU."));
    return;
  }

  Device* src_device;
  Status s = device_mgr_->LookupDevice(parsed.src_device, &src_device);
  if (!s.ok()) {
    done(s);
    return;
  }
  Device* dst_device;
  s = device_mgr_->LookupDevice(parsed.dst_device, &dst_device);
  if (!s.ok()) {
    done(s);
    return;
  }

  AllocatorAttributes attr = recv_args.alloc_attrs;
  attr.set_gpu_compatible(send_args.alloc_attrs.gpu_compatible() ||
                          recv_args.alloc_attrs.gpu_compatible());
  Allocator* out_allocator = dst_device->GetAllocator(attr);
  if (in.dtype() != DT_VARIANT) {
    // Variants are handled by CopyTensor::ViaDMA.
    Tensor copy(out_allocator, in.dtype(), in.shape());
    *out = copy;
  }

  CopyTensor::ViaDMA(parsed.edge_name, send_args.device_context,
                     recv_args.device_context, src_device, dst_device,
                     send_args.alloc_attrs, recv_args.alloc_attrs, &in, out,
                     std::move(done));
}

void IntraProcessRendezvous::RecvAsync(const ParsedKey& parsed,
                                       const Rendezvous::Args& recv_args,
                                       DoneCallback done) {
  VLOG(1) << "IntraProcessRendezvous Recv " << this << " " << parsed.FullKey();

  // Recv the tensor from local_.
  local_->RecvAsync(
      parsed, recv_args,
      [this, parsed, done](
          const Status& status, const Rendezvous::Args& send_args,
          const Rendezvous::Args& recv_args, const Tensor& in, bool is_dead) {
        // If "in" is an uninitialized tensor, do copy-construction to preserve
        // the uninitialized state, along with data type and shape info, which
        // is useful for debugger purposes.
        Tensor* out = in.IsInitialized() ? new Tensor : new Tensor(in);

        StatusCallback final_callback = [done, send_args, recv_args, out,
                                         is_dead](const Status& s) {
          done(s, send_args, recv_args, *out, is_dead);
          delete out;
        };

        if (status.ok() && in.IsInitialized()) {
          SameWorkerRecvDone(parsed, send_args, recv_args, in, out,
                             std::move(final_callback));
        } else {
          final_callback(status);
        }
      });
}

void IntraProcessRendezvous::StartAbort(const Status& s) {
  CHECK(!s.ok());
  local_->StartAbort(s);
}

}  // end namespace tensorflow
<commit_msg>Move callback into bound function to avoid copying.<commit_after>/* Copyright 2015 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#include "tensorflow/core/common_runtime/rendezvous_mgr.h"

#include <unordered_set>

#include "tensorflow/core/common_runtime/copy_tensor.h"
#include "tensorflow/core/common_runtime/device.h"
#include "tensorflow/core/common_runtime/device_mgr.h"
#include "tensorflow/core/framework/types.h"
#include "tensorflow/core/lib/core/errors.h"
#include "tensorflow/core/lib/core/notification.h"
#include "tensorflow/core/lib/strings/numbers.h"
#include "tensorflow/core/lib/strings/str_util.h"
#include "tensorflow/core/platform/logging.h"
#include "tensorflow/core/platform/mutex.h"
#include "tensorflow/core/platform/types.h"

namespace tensorflow {

IntraProcessRendezvous::IntraProcessRendezvous(const DeviceMgr* device_mgr)
    : device_mgr_(device_mgr), local_(NewLocalRendezvous()) {}

IntraProcessRendezvous::~IntraProcessRendezvous() { local_->Unref(); }

Status IntraProcessRendezvous::Send(const ParsedKey& parsed,
                                    const Rendezvous::Args& args,
                                    const Tensor& val, const bool is_dead) {
  VLOG(1) << "IntraProcessRendezvous Send " << this << " " << parsed.FullKey();
  {
    mutex_lock l(mu_);
    if (!status_.ok()) return status_;
  }

  // Buffers "val" and "device_context" in local_.
  return local_->Send(parsed, args, val, is_dead);
}

Status IntraProcessRendezvous::ParseKey(const string& key, bool is_src,
                                        Rendezvous::ParsedKey* parsed) {
  {
    mutex_lock l(mu_);
    if (!status_.ok()) return status_;
  }
  TF_RETURN_IF_ERROR(Rendezvous::ParseKey(key, parsed));
  return Status::OK();
}

void IntraProcessRendezvous::SameWorkerRecvDone(
    const Rendezvous::ParsedKey& parsed, const Rendezvous::Args& send_args,
    const Rendezvous::Args& recv_args, const Tensor& in, Tensor* out,
    StatusCallback done) {
  // Do a quick copy (sharing the underlying buffer) if both tensors
  // are on host memory.
  const bool src_host =
      (send_args.alloc_attrs.on_host() || parsed.src.type == "CPU");
  const bool dst_host =
      (recv_args.alloc_attrs.on_host() || parsed.dst.type == "CPU");
  if (src_host && dst_host) {
    *out = in;
    done(Status::OK());
    return;
  }

  // This copy must involve a non-CPU device. Hence, "in" must support DMA
  // (e.g., string tensors do not work on GPU).  Variant copy DMA
  // checks happen inside CopyTensor::ViaDMA.
  if (!DataTypeCanUseMemcpy(in.dtype()) && in.dtype() != DT_VARIANT) {
    done(errors::InvalidArgument("Non-DMA-safe ", DataTypeString(in.dtype()),
                                 " tensor may not be copied from/to a GPU."));
    return;
  }

  Device* src_device;
  Status s = device_mgr_->LookupDevice(parsed.src_device, &src_device);
  if (!s.ok()) {
    done(s);
    return;
  }
  Device* dst_device;
  s = device_mgr_->LookupDevice(parsed.dst_device, &dst_device);
  if (!s.ok()) {
    done(s);
    return;
  }

  AllocatorAttributes attr = recv_args.alloc_attrs;
  attr.set_gpu_compatible(send_args.alloc_attrs.gpu_compatible() ||
                          recv_args.alloc_attrs.gpu_compatible());
  Allocator* out_allocator = dst_device->GetAllocator(attr);
  if (in.dtype() != DT_VARIANT) {
    // Variants are handled by CopyTensor::ViaDMA.
    Tensor copy(out_allocator, in.dtype(), in.shape());
    *out = copy;
  }

  CopyTensor::ViaDMA(parsed.edge_name, send_args.device_context,
                     recv_args.device_context, src_device, dst_device,
                     send_args.alloc_attrs, recv_args.alloc_attrs, &in, out,
                     std::move(done));
}

void IntraProcessRendezvous::RecvAsync(const ParsedKey& parsed,
                                       const Rendezvous::Args& recv_args,
                                       DoneCallback done) {
  VLOG(1) << "IntraProcessRendezvous Recv " << this << " " << parsed.FullKey();

  // Recv the tensor from local_.
  local_->RecvAsync(
      parsed, recv_args,
      std::bind(
          [this, parsed](DoneCallback done,
                         // Begin unbound arguments.
                         const Status& status,
                         const Rendezvous::Args& send_args,
                         const Rendezvous::Args& recv_args, const Tensor& in,
                         bool is_dead) {
            // If "in" is an uninitialized tensor, do copy-construction to
            // preserve the uninitialized state, along with data type and shape
            // info, which is useful for debugger purposes.
            Tensor* out = in.IsInitialized() ? new Tensor : new Tensor(in);

            auto final_callback = std::bind(
                [send_args, recv_args, out, is_dead](DoneCallback done,
                                                     // Begin unbound arguments.
                                                     const Status& s) {
                  done(s, send_args, recv_args, *out, is_dead);
                  delete out;
                },
                std::move(done), std::placeholders::_1);

            if (status.ok() && in.IsInitialized()) {
              SameWorkerRecvDone(parsed, send_args, recv_args, in, out,
                                 std::move(final_callback));
            } else {
              final_callback(status);
            }
          },
          std::move(done), std::placeholders::_1, std::placeholders::_2,
          std::placeholders::_3, std::placeholders::_4, std::placeholders::_5));
}

void IntraProcessRendezvous::StartAbort(const Status& s) {
  CHECK(!s.ok());
  local_->StartAbort(s);
}

}  // end namespace tensorflow
<|endoftext|>


<commit_before>/* This file is part of Ingen.
 * Copyright (C) 2007 Dave Robillard <http://drobilla.net>
 *
 * Ingen is free software; you can redistribute it and/or modify it under the
 * terms of the GNU General Public License as published by the Free Software
 * Foundation; either version 2 of the License, or (at your option) any later
 * version.
 *
 * Ingen 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 details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
 */

#include <cassert>
#include <raul/Atom.hpp>
#include "interface/EngineInterface.hpp"
#include "client/PatchModel.hpp"
#include "client/NodeModel.hpp"
#include "App.hpp"
#include "NodeModule.hpp"
#include "PatchCanvas.hpp"
#include "Port.hpp"
#include "GladeFactory.hpp"
#include "RenameWindow.hpp"
#include "PatchWindow.hpp"
#include "WindowFactory.hpp"
#include "SubpatchModule.hpp"
#include "NodeControlWindow.hpp"

namespace Ingen {
namespace GUI {

NodeModule::NodeModule(boost::shared_ptr<PatchCanvas> canvas, SharedPtr<NodeModel> node)
	: FlowCanvas::Module(canvas, node->path().name())
	, _node(node)
	, _gui(NULL)
	, _gui_item(NULL)
{
	assert(_node);

	Glib::RefPtr<Gnome::Glade::Xml> xml = GladeFactory::new_glade_reference();
	xml->get_widget_derived("object_menu", _menu);
	_menu->init(node);
	set_menu(_menu);

	node->signal_new_port.connect(sigc::bind(sigc::mem_fun(this, &NodeModule::add_port), true));
	node->signal_removed_port.connect(sigc::mem_fun(this, &NodeModule::remove_port));
	node->signal_metadata.connect(sigc::mem_fun(this, &NodeModule::set_metadata));
	node->signal_polyphonic.connect(sigc::mem_fun(this, &NodeModule::set_stacked_border));
	node->signal_renamed.connect(sigc::mem_fun(this, &NodeModule::rename));

	_menu->signal_embed_gui.connect(sigc::mem_fun(this, &NodeModule::embed_gui));

	set_stacked_border(node->polyphonic());
}

NodeModule::~NodeModule()
{
	NodeControlWindow* win = App::instance().window_factory()->control_window(_node);

	if (win) {
		// Should remove from window factory via signal
		delete win;
	}
}

boost::shared_ptr<NodeModule>
NodeModule::create(boost::shared_ptr<PatchCanvas> canvas, SharedPtr<NodeModel> node)
{
	boost::shared_ptr<NodeModule> ret;

	SharedPtr<PatchModel> patch = PtrCast<PatchModel>(node);
	if (patch)
		ret = boost::shared_ptr<NodeModule>(new SubpatchModule(canvas, patch));
	else
		ret = boost::shared_ptr<NodeModule>(new NodeModule(canvas, node));

	for (MetadataMap::const_iterator m = node->metadata().begin(); m != node->metadata().end(); ++m)
		ret->set_metadata(m->first, m->second);

	for (PortModelList::const_iterator p = node->ports().begin(); p != node->ports().end(); ++p)
		ret->add_port(*p, false);

	ret->resize();

	return ret;
}

void
NodeModule::embed_gui(bool embed)
{
	if (embed) {

		GtkWidget* c_widget = NULL;

		if (!_gui_item) {
			cerr << "Embedding LV2 GUI" << endl;
			// FIXME: leaks?
			SLV2UIInstance ui = _node->plugin()->ui(App::instance().engine().get(), _node.get());
			if (ui) {
				cerr << "Found UI" << endl;
				c_widget = (GtkWidget*)slv2_ui_instance_get_widget(ui);
				_gui = Glib::wrap(c_widget);
				assert(_gui);
				const double y = 4 + _canvas_title.property_text_height();
				_gui_item = new Gnome::Canvas::Widget(/**_canvas.lock()->root()*/*this, 2.0, y, *_gui);
			}
		}

		if (_gui_item) {
			assert(_gui);
			cerr << "Created canvas item" << endl;
			_gui->show();
			_gui->show_all();
			_gui_item->show();
			GtkRequisition r;
			gtk_widget_size_request(c_widget, &r);
			cerr << "Size request: " << r.width << "x" << r.height << endl;
			_width = max(_width, (double)r.width);
			_height = max(_height, (double)r.height);
			_gui_item->property_width() = _width - 2;
			_gui_item->property_height() = _height;
			_gui_item->raise_to_top();
			_ports_y_offset = _height + 2;
			set_width(_width);
		} else {
			cerr << "*** Failed to create canvas item" << endl;
		}

	} else {
		if (_gui_item)
			_gui_item->hide();

		_ports_y_offset = 0;
	}

	resize();
}

void
NodeModule::rename()
{
	set_name(_node->path().name());
}

void
NodeModule::add_port(SharedPtr<PortModel> port, bool resize_to_fit)
{
	Module::add_port(boost::shared_ptr<Port>(new Port(
			PtrCast<NodeModule>(shared_from_this()), port)));

	if (resize_to_fit)
		resize();
}

void
NodeModule::remove_port(SharedPtr<PortModel> port)
{
	SharedPtr<FlowCanvas::Port> p = Module::remove_port(port->path().name());
	p.reset();
}

void
NodeModule::show_control_window()
{
#ifdef HAVE_SLV2
	if (_node->plugin()->type() == PluginModel::LV2) {
		// FIXME: check type

		SLV2UIInstance ui = _node->plugin()->ui(App::instance().engine().get(), _node.get());
		if (ui) {
			cerr << "Showing LV2 GUI" << endl;
			// FIXME: leak
			GtkWidget* c_widget = (GtkWidget*)slv2_ui_instance_get_widget(ui);
			Gtk::Widget* widget = Glib::wrap(c_widget);

			Gtk::Window* win = new Gtk::Window();
			win->add(*widget);
			widget->show_all();
			win->show_all();
			win->present();
			widget->show_all();
			win->show_all();
		} else {
			cerr << "No LV2 GUI, showing builtin controls" << endl;
			App::instance().window_factory()->present_controls(_node);
		}
	} else {
		App::instance().window_factory()->present_controls(_node);
	}
#else
	App::instance().window_factory()->present_controls(_node);
#endif
}

void
NodeModule::store_location()
{
	const float x = static_cast<float>(property_x());
	const float y = static_cast<float>(property_y());

	const Atom& existing_x = _node->get_metadata("ingenuity:canvas-x");
	const Atom& existing_y = _node->get_metadata("ingenuity:canvas-y");

	if (existing_x.type() != Atom::FLOAT || existing_y.type() != Atom::FLOAT
			|| existing_x.get_float() != x || existing_y.get_float() != y) {
		App::instance().engine()->set_metadata(_node->path(), "ingenuity:canvas-x", Atom(x));
		App::instance().engine()->set_metadata(_node->path(), "ingenuity:canvas-y", Atom(y));
	}
}

void
NodeModule::set_metadata(const string& key, const Atom& value)
{
	if (key == "ingenuity:canvas-x" && value.type() == Atom::FLOAT)
		move_to(value.get_float(), property_y());
	else if (key == "ingenuity:canvas-y" && value.type() == Atom::FLOAT)
		move_to(property_x(), value.get_float());
}

} // namespace GUI
} // namespace Ingen
<commit_msg>LV2 GUI embedding w/ proper sizing.<commit_after>/* This file is part of Ingen.
 * Copyright (C) 2007 Dave Robillard <http://drobilla.net>
 *
 * Ingen is free software; you can redistribute it and/or modify it under the
 * terms of the GNU General Public License as published by the Free Software
 * Foundation; either version 2 of the License, or (at your option) any later
 * version.
 *
 * Ingen 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 details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
 */

#include <cassert>
#include <raul/Atom.hpp>
#include "interface/EngineInterface.hpp"
#include "client/PatchModel.hpp"
#include "client/NodeModel.hpp"
#include "App.hpp"
#include "NodeModule.hpp"
#include "PatchCanvas.hpp"
#include "Port.hpp"
#include "GladeFactory.hpp"
#include "RenameWindow.hpp"
#include "PatchWindow.hpp"
#include "WindowFactory.hpp"
#include "SubpatchModule.hpp"
#include "NodeControlWindow.hpp"

namespace Ingen {
namespace GUI {

NodeModule::NodeModule(boost::shared_ptr<PatchCanvas> canvas, SharedPtr<NodeModel> node)
	: FlowCanvas::Module(canvas, node->path().name())
	, _node(node)
	, _gui(NULL)
	, _gui_item(NULL)
{
	assert(_node);

	Glib::RefPtr<Gnome::Glade::Xml> xml = GladeFactory::new_glade_reference();
	xml->get_widget_derived("object_menu", _menu);
	_menu->init(node);
	set_menu(_menu);

	node->signal_new_port.connect(sigc::bind(sigc::mem_fun(this, &NodeModule::add_port), true));
	node->signal_removed_port.connect(sigc::mem_fun(this, &NodeModule::remove_port));
	node->signal_metadata.connect(sigc::mem_fun(this, &NodeModule::set_metadata));
	node->signal_polyphonic.connect(sigc::mem_fun(this, &NodeModule::set_stacked_border));
	node->signal_renamed.connect(sigc::mem_fun(this, &NodeModule::rename));

	_menu->signal_embed_gui.connect(sigc::mem_fun(this, &NodeModule::embed_gui));

	set_stacked_border(node->polyphonic());
}

NodeModule::~NodeModule()
{
	NodeControlWindow* win = App::instance().window_factory()->control_window(_node);

	if (win) {
		// Should remove from window factory via signal
		delete win;
	}
}

boost::shared_ptr<NodeModule>
NodeModule::create(boost::shared_ptr<PatchCanvas> canvas, SharedPtr<NodeModel> node)
{
	boost::shared_ptr<NodeModule> ret;

	SharedPtr<PatchModel> patch = PtrCast<PatchModel>(node);
	if (patch)
		ret = boost::shared_ptr<NodeModule>(new SubpatchModule(canvas, patch));
	else
		ret = boost::shared_ptr<NodeModule>(new NodeModule(canvas, node));

	for (MetadataMap::const_iterator m = node->metadata().begin(); m != node->metadata().end(); ++m)
		ret->set_metadata(m->first, m->second);

	for (PortModelList::const_iterator p = node->ports().begin(); p != node->ports().end(); ++p)
		ret->add_port(*p, false);

	ret->resize();

	return ret;
}

void
NodeModule::embed_gui(bool embed)
{
	if (embed) {

		// FIXME: leaks?

		GtkWidget* c_widget = NULL;
		Gtk::EventBox* container = NULL;

		if (!_gui_item) {
			cerr << "Embedding LV2 GUI" << endl;

			SLV2UIInstance ui = _node->plugin()->ui(App::instance().engine().get(), _node.get());
			if (ui) {
				cerr << "Found UI" << endl;
				c_widget = (GtkWidget*)slv2_ui_instance_get_widget(ui);
				_gui = Glib::wrap(c_widget);
				assert(_gui);

				/* Kludge, show in window to get size */
				container = new Gtk::EventBox();
				container->add(*_gui);
				container->show_all();

				const double y = 4 + _canvas_title.property_text_height();
				_gui_item = new Gnome::Canvas::Widget(*this, 2.0, y, *container);
			}
		}

		if (_gui_item) {
			assert(_gui);
			cerr << "Created canvas item" << endl;
			_gui->show();
			_gui->show_all();
			_gui_item->show();

			GtkRequisition r;
			gtk_widget_size_request(c_widget, &r);
			cerr << "Size request: " << r.width << "x" << r.height << endl;

			if (r.width + 4 > _width)
				set_width(r.width + 4);

			_height = max(_height, (double)r.height);
			_gui_item->property_width() = _width - 4;
			_gui_item->property_height() = r.height;
			_gui_item->raise_to_top();
			_ports_y_offset = r.height + 2;

		} else {
			cerr << "*** Failed to create canvas item" << endl;
		}

	} else {
		if (_gui_item)
			_gui_item->hide();

		_ports_y_offset = 0;
	}

	resize();
}

void
NodeModule::rename()
{
	set_name(_node->path().name());
}

void
NodeModule::add_port(SharedPtr<PortModel> port, bool resize_to_fit)
{
	Module::add_port(boost::shared_ptr<Port>(new Port(
			PtrCast<NodeModule>(shared_from_this()), port)));

	if (resize_to_fit)
		resize();
}

void
NodeModule::remove_port(SharedPtr<PortModel> port)
{
	SharedPtr<FlowCanvas::Port> p = Module::remove_port(port->path().name());
	p.reset();
}

void
NodeModule::show_control_window()
{
#ifdef HAVE_SLV2
	if (_node->plugin()->type() == PluginModel::LV2) {
		// FIXME: check type

		SLV2UIInstance ui = _node->plugin()->ui(App::instance().engine().get(), _node.get());
		if (ui) {
			cerr << "Showing LV2 GUI" << endl;
			// FIXME: leak
			GtkWidget* c_widget = (GtkWidget*)slv2_ui_instance_get_widget(ui);
			Gtk::Widget* widget = Glib::wrap(c_widget);

			Gtk::Window* win = new Gtk::Window();
			win->add(*widget);
			widget->show_all();
			win->present();
		} else {
			cerr << "No LV2 GUI, showing builtin controls" << endl;
			App::instance().window_factory()->present_controls(_node);
		}
	} else {
		App::instance().window_factory()->present_controls(_node);
	}
#else
	App::instance().window_factory()->present_controls(_node);
#endif
}

void
NodeModule::store_location()
{
	const float x = static_cast<float>(property_x());
	const float y = static_cast<float>(property_y());

	const Atom& existing_x = _node->get_metadata("ingenuity:canvas-x");
	const Atom& existing_y = _node->get_metadata("ingenuity:canvas-y");

	if (existing_x.type() != Atom::FLOAT || existing_y.type() != Atom::FLOAT
			|| existing_x.get_float() != x || existing_y.get_float() != y) {
		App::instance().engine()->set_metadata(_node->path(), "ingenuity:canvas-x", Atom(x));
		App::instance().engine()->set_metadata(_node->path(), "ingenuity:canvas-y", Atom(y));
	}
}

void
NodeModule::set_metadata(const string& key, const Atom& value)
{
	if (key == "ingenuity:canvas-x" && value.type() == Atom::FLOAT)
		move_to(value.get_float(), property_y());
	else if (key == "ingenuity:canvas-y" && value.type() == Atom::FLOAT)
		move_to(property_x(), value.get_float());
}

} // namespace GUI
} // namespace Ingen
<|endoftext|>


<commit_before>// Ignore unused parameter warnings coming from cppuint headers
#include <libmesh/ignore_warnings.h>
#include <cppunit/extensions/HelperMacros.h>
#include <cppunit/TestCase.h>
#include <libmesh/restore_warnings.h>

#include <libmesh/equation_systems.h>
#include <libmesh/mesh.h>
#include <libmesh/mesh_generation.h>

#include "test_comm.h"

using namespace libMesh;

class EquationSystemsTest : public CppUnit::TestCase {
public:
  CPPUNIT_TEST_SUITE( EquationSystemsTest );

  CPPUNIT_TEST( testConstruction );
  CPPUNIT_TEST( testAddSystem );
  CPPUNIT_TEST( testInit );
  CPPUNIT_TEST( testPostInitAddSystem );

  CPPUNIT_TEST_SUITE_END();

private:

public:
  void setUp()
  {}

  void tearDown()
  {}

  void testConstruction()
  {
    Mesh mesh(*TestCommWorld);
    EquationSystems es(mesh);
  }

  void testAddSystem()
  {
    Mesh mesh(*TestCommWorld);
    EquationSystems es(mesh);
    /*System &sys = */es.add_system<System> ("SimpleSystem");
  }

  void testInit()
  {
    Mesh mesh(*TestCommWorld);
    EquationSystems es(mesh);
    /*System &sys = */es.add_system<System> ("SimpleSystem");
    MeshTools::Generation::build_point(mesh);
    es.init();
  }

  void testPostInitAddSystem()
  {
    Mesh mesh(*TestCommWorld);
    MeshTools::Generation::build_point(mesh);
    EquationSystems es(mesh);
    /*System &sys1 = */es.add_system<System> ("SimpleSystem");
    es.init();
    /*System &sys2 = */es.add_system<System> ("SecondSystem");
    es.reinit();
  }

  void testPostInitAddRealSystem()
  {
    Mesh mesh(*TestCommWorld);
    MeshTools::Generation::build_point(mesh);
    EquationSystems es(mesh);
    System &sys1 = es.add_system<System> ("SimpleSystem");
    sys1.add_variable("u1", FIRST);
    es.init();
    System &sys2 = es.add_system<System> ("SecondSystem");
    sys2.add_variable("u2", FIRST);
    es.reinit();
  }

};

CPPUNIT_TEST_SUITE_REGISTRATION( EquationSystemsTest );
<commit_msg>Add test for ES::reinit() with newly added Elem<commit_after>// Ignore unused parameter warnings coming from cppuint headers
#include <libmesh/ignore_warnings.h>
#include <cppunit/extensions/HelperMacros.h>
#include <cppunit/TestCase.h>
#include <libmesh/restore_warnings.h>

#include <libmesh/equation_systems.h>
#include <libmesh/mesh.h>
#include <libmesh/mesh_generation.h>

#include "test_comm.h"

using namespace libMesh;

class EquationSystemsTest : public CppUnit::TestCase {
public:
  CPPUNIT_TEST_SUITE( EquationSystemsTest );

  CPPUNIT_TEST( testConstruction );
  CPPUNIT_TEST( testAddSystem );
  CPPUNIT_TEST( testInit );
  CPPUNIT_TEST( testPostInitAddSystem );
  CPPUNIT_TEST( testPostInitAddElem );

  CPPUNIT_TEST_SUITE_END();

private:

public:
  void setUp()
  {}

  void tearDown()
  {}

  void testConstruction()
  {
    Mesh mesh(*TestCommWorld);
    EquationSystems es(mesh);
  }

  void testAddSystem()
  {
    Mesh mesh(*TestCommWorld);
    EquationSystems es(mesh);
    /*System &sys = */es.add_system<System> ("SimpleSystem");
  }

  void testInit()
  {
    Mesh mesh(*TestCommWorld);
    EquationSystems es(mesh);
    /*System &sys = */es.add_system<System> ("SimpleSystem");
    MeshTools::Generation::build_point(mesh);
    es.init();
  }

  void testPostInitAddSystem()
  {
    Mesh mesh(*TestCommWorld);
    MeshTools::Generation::build_point(mesh);
    EquationSystems es(mesh);
    /*System &sys1 = */es.add_system<System> ("SimpleSystem");
    es.init();
    /*System &sys2 = */es.add_system<System> ("SecondSystem");
    es.reinit();
  }

  void testPostInitAddRealSystem()
  {
    Mesh mesh(*TestCommWorld);
    MeshTools::Generation::build_point(mesh);
    EquationSystems es(mesh);
    System &sys1 = es.add_system<System> ("SimpleSystem");
    sys1.add_variable("u1", FIRST);
    es.init();
    System &sys2 = es.add_system<System> ("SecondSystem");
    sys2.add_variable("u2", FIRST);
    es.reinit();
  }

  void testPostInitAddElem()
  {
    Mesh mesh(*TestCommWorld);

    EquationSystems es(mesh);
    System &sys = es.add_system<System> ("SimpleSystem");
    sys.add_variable("u", FIRST);

    MeshTools::Generation::build_line (mesh, 10, 0., 1., EDGE2);
    es.init();

    Elem* e = Elem::build(EDGE2).release();
    e->set_id(mesh.max_elem_id());
    e->processor_id() = 0;
    e->set_node(0) = mesh.node_ptr(2);
    e->set_node(1) = mesh.node_ptr(8);
    mesh.add_elem(e);
    mesh.prepare_for_use();

    es.reinit();
  }

};

CPPUNIT_TEST_SUITE_REGISTRATION( EquationSystemsTest );
<|endoftext|>


<commit_before>#include <iostream>
#include <algorithm>
#include <random>

#include <simulated_annealing.hpp>

struct City{
    float x;
    float y;
};

float distance(const City& c1, const City& c2)
{
    return std::hypot(c2.x - c1.x, c2.y - c1.y);
}

using Trajectory = std::vector<City>;

std::ostream& operator<<(std::ostream& o, const Trajectory& t)
{
    for (auto& c : t)
        o << "[" << c.x << ", " << c.y << "], ";

    return o;
}

struct Generator{
    Trajectory operator()(const Trajectory& t, const SimulatedAnnealing& sa) const
    {
        Trajectory t2 = t;

        std::shuffle(begin(t2), end(t2), std::default_random_engine{});

        return t2;
    }
};

struct Energy{

    float operator()(const Trajectory& t) const
    {
        std::vector<float> distances;

        for (int i = 1; i < t.size(); ++i)
            distances.push_back(distance(t[i-1], t[i]));

        return std::accumulate(begin(distances), end(distances), 0.0);
    }
};

int main()
{
    Energy energy;
    Generator generator;

    // City clermont_ferrand{0, 0}; //center of the universe
    // City madrid{-10, -100};
    // City new_york{-1000, 20};
    // City shanghai{+5000, -100};
    // Trajectory trajectory{clermont_ferrand, madrid, new_york, shanghai};

    // City c0 {0.0, 0.0};
    // City c1 {1.0, 0.0};
    // City c2 {2.0, 0.0};
    // City c3 {3.0, 0.0};
    // City c4 {4.0, 0.0};
    // City c5 {5.0, 0.0};
    // City c6 {6.0, 0.0};
    // City c7 {7.0, 0.0};
    // City c8 {8.0, 0.0};
    // City c9 {9.0, 0.0};
    // City c10 {10.0, 0.0};
    // City c11 {11.0, 0.0};
    // City c12 {12.0, 0.0};
    // City c13 {13.0, 0.0};
    // City c14 {14.0, 0.0};
    // City c15 {15.0, 0.0};
    // Trajectory trajectory{c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15};

    City c0 { 200.0,  800.0};
    City c1 {3600.0, 2300.0};
    City c2 {3100.0, 3300.0};
    City c3 {4700.0, 5750.0};
    City c4 {5400.0, 5750.0};
    City c5 {5608.0, 7103.0};
    City c6 {4493.0, 7102.0};
    City c7 {3600.0, 6950.0};
    Trajectory trajectory{c0, c1, c2, c3, c4, c5, c6, c7};

    std::cout << "Optimal trajectory: " << trajectory << std::endl;
    std::cout << "Optimal distance: " << energy(trajectory) << std::endl;

    SimulatedAnnealing sim(
          1e3                // start temp
        , 1e-1               // stop temp
        , int(1e4)           // max it
        , energy(trajectory) // energy min
        );

    std::shuffle(begin(trajectory), end(trajectory), std::default_random_engine{});

    std::cout << "Initial trajectory: " << trajectory << std::endl;

    sim(energy, trajectory, generator);

    std::cout << "Final trajectory: " << trajectory << std::endl;

    return 0;
}
<commit_msg>[traveling_salesman] fixed warning<commit_after>#include <iostream>
#include <algorithm>
#include <random>

#include <simulated_annealing.hpp>

struct City{
    float x;
    float y;
};

float distance(const City& c1, const City& c2)
{
    return std::hypot(c2.x - c1.x, c2.y - c1.y);
}

using Trajectory = std::vector<City>;

std::ostream& operator<<(std::ostream& o, const Trajectory& t)
{
    for (auto& c : t)
        o << "[" << c.x << ", " << c.y << "], ";

    return o;
}

struct Generator{
    Trajectory operator()(const Trajectory& t, const SimulatedAnnealing& sa) const
    {
        Trajectory t2 = t;

        std::shuffle(begin(t2), end(t2), std::default_random_engine{});

        return t2;
    }
};

struct Energy{
    float operator()(const Trajectory& t) const
    {
        std::vector<float> distances;

        for (int i = 1; i < t.size(); ++i)
            distances.push_back(distance(t[i-1], t[i]));

        return std::accumulate(begin(distances), end(distances), 0.0);
    }
};

int main()
{
    Energy energy;
    Generator generator;

    City c0 { 200.0,  800.0};
    City c1 {3600.0, 2300.0};
    City c2 {3100.0, 3300.0};
    City c3 {4700.0, 5750.0};
    City c4 {5400.0, 5750.0};
    City c5 {5608.0, 7103.0};
    City c6 {4493.0, 7102.0};
    City c7 {3600.0, 6950.0};
    Trajectory trajectory{c0, c1, c2, c3, c4, c5, c6, c7};

    std::cout << "Optimal trajectory: " << trajectory << std::endl;
    std::cout << "Optimal distance: " << energy(trajectory) << std::endl;

    SimulatedAnnealing sim(1e3, // start temp
                           1e-1, // stop temp
                           int(1e4), // max it
                           energy(trajectory)); // energy min

    std::shuffle(begin(trajectory), end(trajectory), std::default_random_engine{});

    std::cout << "Initial trajectory: " << trajectory << std::endl;

    sim(energy, trajectory, generator);

    std::cout << "Final trajectory: " << trajectory << std::endl;

    return 0;
}
<|endoftext|>


<commit_before>// Copyright (c) 2019 by Robert Bosch GmbH. All rights reserved.
//
// 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.
//
// SPDX-License-Identifier: Apache-2.0
#ifndef IOX_UTILS_DESIGN_PATTERN_CREATION_HPP
#define IOX_UTILS_DESIGN_PATTERN_CREATION_HPP

#include "iceoryx_utils/cxx/expected.hpp"

namespace DesignPattern
{
template <typename DerivedClass, typename ErrorType>
class Creation
{
  public:
    using CreationPattern_t = Creation<DerivedClass, ErrorType>;
    using result_t = iox::cxx::expected<DerivedClass, ErrorType>;
    using errorType_t = ErrorType;

    template <typename... Targs>
    static result_t create(Targs&&... args) noexcept
    {
        return verify(DerivedClass(std::forward<Targs>(args)...));
    }

    static result_t verify(DerivedClass&& newObject) noexcept
    {
        if (!newObject.m_isInitialized)
        {
            return iox::cxx::error<ErrorType>(newObject.m_errorValue);
        }

        return iox::cxx::success<DerivedClass>(std::move(newObject));
    }

    template <typename... Targs>
    static iox::cxx::expected<ErrorType> placementCreate(void* const memory, Targs&&... args) noexcept
    {
        auto newClass = static_cast<DerivedClass*>(memory);
        new (newClass) DerivedClass(std::forward<Targs>(args)...);

        if (!newClass->m_isInitialized)
        {
            ErrorType errorValue = newClass->m_errorValue;
            newClass->~DerivedClass();
            return iox::cxx::error<ErrorType>(errorValue);
        }

        return iox::cxx::success<>();
    }

    Creation() noexcept = default;

    Creation(Creation&& rhs) noexcept
    {
        *this = std::move(rhs);
    }

    Creation& operator=(Creation&& rhs) noexcept
    {
        if (this != &rhs)
        {
            m_isInitialized = rhs.m_isInitialized;
            m_errorValue = rhs.m_errorValue;
            rhs.m_isInitialized = false;
        }
        return *this;
    }

    Creation(const Creation& rhs) noexcept = default;
    Creation& operator=(const Creation& rhs) noexcept = default;

    bool isInitialized() const noexcept
    {
        return m_isInitialized;
    }

  protected:
    bool m_isInitialized{false};
    ErrorType m_errorValue;
};

} // namespace DesignPattern

#endif // IOX_UTILS_DESIGN_PATTERN_CREATION_HPP
<commit_msg>iox-#542 moved error value as well<commit_after>// Copyright (c) 2019 by Robert Bosch GmbH. All rights reserved.
//
// 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.
//
// SPDX-License-Identifier: Apache-2.0
#ifndef IOX_UTILS_DESIGN_PATTERN_CREATION_HPP
#define IOX_UTILS_DESIGN_PATTERN_CREATION_HPP

#include "iceoryx_utils/cxx/expected.hpp"

namespace DesignPattern
{
template <typename DerivedClass, typename ErrorType>
class Creation
{
  public:
    using CreationPattern_t = Creation<DerivedClass, ErrorType>;
    using result_t = iox::cxx::expected<DerivedClass, ErrorType>;
    using errorType_t = ErrorType;

    template <typename... Targs>
    static result_t create(Targs&&... args) noexcept
    {
        return verify(DerivedClass(std::forward<Targs>(args)...));
    }

    static result_t verify(DerivedClass&& newObject) noexcept
    {
        if (!newObject.m_isInitialized)
        {
            return iox::cxx::error<ErrorType>(newObject.m_errorValue);
        }

        return iox::cxx::success<DerivedClass>(std::move(newObject));
    }

    template <typename... Targs>
    static iox::cxx::expected<ErrorType> placementCreate(void* const memory, Targs&&... args) noexcept
    {
        auto newClass = static_cast<DerivedClass*>(memory);
        new (newClass) DerivedClass(std::forward<Targs>(args)...);

        if (!newClass->m_isInitialized)
        {
            ErrorType errorValue = newClass->m_errorValue;
            newClass->~DerivedClass();
            return iox::cxx::error<ErrorType>(errorValue);
        }

        return iox::cxx::success<>();
    }

    Creation() noexcept = default;

    Creation(Creation&& rhs) noexcept
    {
        *this = std::move(rhs);
    }

    Creation& operator=(Creation&& rhs) noexcept
    {
        if (this != &rhs)
        {
            m_isInitialized = rhs.m_isInitialized;
            m_errorValue = std::move(rhs.m_errorValue);
            rhs.m_isInitialized = false;
        }
        return *this;
    }

    Creation(const Creation& rhs) noexcept = default;
    Creation& operator=(const Creation& rhs) noexcept = default;

    bool isInitialized() const noexcept
    {
        return m_isInitialized;
    }

  protected:
    bool m_isInitialized{false};
    ErrorType m_errorValue;
};

} // namespace DesignPattern

#endif // IOX_UTILS_DESIGN_PATTERN_CREATION_HPP
<|endoftext|>


<commit_before>/**
 * ****************************************************************************
 * Copyright (c) 2017, Robert Lukierski.
 * 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.
 *
 * Neither the name of the copyright holder nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * 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.
 *
 * ****************************************************************************
 * Transform feedback.
 * ****************************************************************************
 */

#ifndef VISIONCORE_WRAPGL_TRANSFORM_FEEDBACK_IMPL_HPP
#define VISIONCORE_WRAPGL_TRANSFORM_FEEDBACK_IMPL_HPP

inline vc::wrapgl::TransformFeedback::TransformFeedback() : tbid(0)
{
    create();
}

inline vc::wrapgl::TransformFeedback::~TransformFeedback()
{
    destroy();
}

inline void vc::wrapgl::TransformFeedback::create()
{
    destroy();

    glGenTransformFeedbacks(1, &tbid);
    WRAPGL_CHECK_ERROR();
}

inline void vc::wrapgl::TransformFeedback::destroy()
{
    if(tbid != 0)
    {
        glDeleteTransformFeedbacks(1, &tbid);
        WRAPGL_CHECK_ERROR();
        tbid = 0;
    }
}

inline bool vc::wrapgl::TransformFeedback::isValid() const
{
    return tbid != 0;
}

inline void vc::wrapgl::TransformFeedback::bind() const
{
    glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, tbid);
    WRAPGL_CHECK_ERROR();
}

inline void vc::wrapgl::TransformFeedback::unbind() const
{
    glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, tbid);
    WRAPGL_CHECK_ERROR();
}

inline void vc::wrapgl::TransformFeedback::draw(GLenum mode) const
{
    glDrawTransformFeedback(mode, tbid);
    WRAPGL_CHECK_ERROR();
}

inline void vc::wrapgl::TransformFeedback::draw(GLenum mode, GLsizei instcnt) const
{
    glDrawTransformFeedbackInstanced(mode, tbid, instcnt);
    WRAPGL_CHECK_ERROR();
}

inline void vc::wrapgl::TransformFeedback::begin(GLenum primode)
{
    glBeginTransformFeedback(primode);
    WRAPGL_CHECK_ERROR();
}

inline void vc::wrapgl::TransformFeedback::end()
{
    glEndTransformFeedback();
    WRAPGL_CHECK_ERROR();
}

inline void vc::wrapgl::TransformFeedback::pause()
{
    glPauseTransformFeedback();
    WRAPGL_CHECK_ERROR();
}

inline void vc::wrapgl::TransformFeedback::resume()
{
    glPauseTransformFeedback();
    WRAPGL_CHECK_ERROR();
}

inline GLuint vc::wrapgl::TransformFeedback::id() const
{
    return tbid;
}

#endif // VISIONCORE_WRAPGL_TRANSFORM_FEEDBACK_IMPL_HPP
<commit_msg>Minor bug<commit_after>/**
 * ****************************************************************************
 * Copyright (c) 2017, Robert Lukierski.
 * 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.
 *
 * Neither the name of the copyright holder nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * 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.
 *
 * ****************************************************************************
 * Transform feedback.
 * ****************************************************************************
 */

#ifndef VISIONCORE_WRAPGL_TRANSFORM_FEEDBACK_IMPL_HPP
#define VISIONCORE_WRAPGL_TRANSFORM_FEEDBACK_IMPL_HPP

inline vc::wrapgl::TransformFeedback::TransformFeedback() : tbid(0)
{
    create();
}

inline vc::wrapgl::TransformFeedback::~TransformFeedback()
{
    destroy();
}

inline void vc::wrapgl::TransformFeedback::create()
{
    destroy();

    glGenTransformFeedbacks(1, &tbid);
    WRAPGL_CHECK_ERROR();
}

inline void vc::wrapgl::TransformFeedback::destroy()
{
    if(tbid != 0)
    {
        glDeleteTransformFeedbacks(1, &tbid);
        WRAPGL_CHECK_ERROR();
        tbid = 0;
    }
}

inline bool vc::wrapgl::TransformFeedback::isValid() const
{
    return tbid != 0;
}

inline void vc::wrapgl::TransformFeedback::bind() const
{
    glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, tbid);
    WRAPGL_CHECK_ERROR();
}

inline void vc::wrapgl::TransformFeedback::unbind() const
{
    glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0);
    WRAPGL_CHECK_ERROR();
}

inline void vc::wrapgl::TransformFeedback::draw(GLenum mode) const
{
    glDrawTransformFeedback(mode, tbid);
    WRAPGL_CHECK_ERROR();
}

inline void vc::wrapgl::TransformFeedback::draw(GLenum mode, GLsizei instcnt) const
{
    glDrawTransformFeedbackInstanced(mode, tbid, instcnt);
    WRAPGL_CHECK_ERROR();
}

inline void vc::wrapgl::TransformFeedback::begin(GLenum primode)
{
    glBeginTransformFeedback(primode);
    WRAPGL_CHECK_ERROR();
}

inline void vc::wrapgl::TransformFeedback::end()
{
    glEndTransformFeedback();
    WRAPGL_CHECK_ERROR();
}

inline void vc::wrapgl::TransformFeedback::pause()
{
    glPauseTransformFeedback();
    WRAPGL_CHECK_ERROR();
}

inline void vc::wrapgl::TransformFeedback::resume()
{
    glPauseTransformFeedback();
    WRAPGL_CHECK_ERROR();
}

inline GLuint vc::wrapgl::TransformFeedback::id() const
{
    return tbid;
}

#endif // VISIONCORE_WRAPGL_TRANSFORM_FEEDBACK_IMPL_HPP
<|endoftext|>


<commit_before> //
 // This file is part of Easylogging++ samples
 // el::Loggable sample
 //
 // Revision 1.0
 // @author mkhan3189
 //

#include "easylogging++.h"

_INITIALIZE_EASYLOGGINGPP

class MyClass : public el::Loggable {
public:
    MyClass(const char* name) : m_name(name) {}

    friend std::ostream& operator<<(std::ostream& os, const MyClass& myclass) {
        os << myclass.m_name;
        return os;
    }
private:
    const char* m_name;
};

int main(void) {
    MyClass c("c");
    MyClass c2("c2");
    LOG(INFO) << c << " " << c2;
    return 0;
}
<commit_msg>minor sample update<commit_after> //
 // This file is part of Easylogging++ samples
 // el::Loggable sample
 //
 // Revision 1.0
 // @author mkhan3189
 //

#include "easylogging++.h"

_INITIALIZE_EASYLOGGINGPP

class MyClass : public el::Loggable {
public:
    MyClass(const char* name) : m_name(name) {}

    friend std::ostream& operator<<(std::ostream& os, const MyClass& myclass) {
        os << myclass.m_name;
        return os;
    }

private:
    const char* m_name;
};

int main(void) {
    MyClass c("c");
    MyClass c2("c2");
    LOG(INFO) << "I am " << c << "; and I am " << c2;
    return 0;
}
<|endoftext|>


<commit_before>/***************************************************************************
 *   Copyright (C) 1998-2010 by authors (see AUTHORS.txt )                 *
 *                                                                         *
 *   This file is part of LuxRays.                                         *
 *                                                                         *
 *   LuxRays is free software; you can redistribute it and/or modify       *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 3 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   LuxRays 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 this program.  If not, see <http://www.gnu.org/licenses/>. *
 *                                                                         *
 *   LuxRays website: http://www.luxrender.net                             *
 ***************************************************************************/

#include <cstdio>
#include <cstdlib>

#include "smalllux.h"
#include "mainwindow.h"
#include "luxmarkapp.h"

static void PrintCmdLineHelp(const QString &cmd) {
	cerr << "Usage: " << cmd.toAscii().data() << " [options]" << endl <<
			" --help <display this help and exit>" << endl <<
			" --scene=<LUXBALL_HDR|SALA|ROOM>" << endl;
}

int main(int argc, char **argv) {
	LuxMarkApp app(argc, argv);

	// Get the arguments into a list
	bool exit = false;

	QStringList argsList = app.arguments();
	QRegExp argHelp("--help");
	QRegExp argScene("--scene=(LUXBALL_HDR|SALA|ROOM)");

	LuxMarkAppMode mode = BENCHMARK_OCL_GPU;
	const char *scnName = SCENE_SALA;
    for (int i = 1; i < argsList.size(); ++i) {
        if (argHelp.indexIn(argsList.at(i)) != -1 ) {
			PrintCmdLineHelp(argsList.at(0));
            exit = true;
			break;
		} else if (argScene.indexIn(argsList.at(i)) != -1 ) {
            QString scene = argScene.cap(1);
			if (scene.compare("LUXBALL_HDR", Qt::CaseInsensitive) == 0)
				scnName = SCENE_LUXBALL_HDR;
			else if (scene.compare("SALA", Qt::CaseInsensitive) == 0)
				scnName = SCENE_SALA;
			else if (scene.compare("ROOM", Qt::CaseInsensitive) == 0)
				scnName = SCENE_ROOM;
			else {
				cerr << "Unknown scene name: " << argScene.cap(1).toAscii().data() << endl;
				PrintCmdLineHelp(argsList.at(0));
				exit = true;
				break;
			}
        } else {
            cerr << "Unknown argument: " << argsList.at(i).toAscii().data() << endl;
			PrintCmdLineHelp(argsList.at(0));
			exit = true;
			break;
        }
    }

	if (exit)
		return EXIT_SUCCESS;
	else {
		app.Init(mode, scnName);

		// Force C locale
		setlocale(LC_NUMERIC,"C");

		if (app.mainWin != NULL)
			return app.exec();
		else
			return EXIT_FAILURE;
	}
}
<commit_msg>LuxMark: added command line option --mode=<BENCHMARK_OCL_GPU|BENCHMARK_OCL_CPUGPU|BENCHMARK_OCL_CPU|INTERACTIVE|PAUSE><commit_after>/***************************************************************************
 *   Copyright (C) 1998-2010 by authors (see AUTHORS.txt )                 *
 *                                                                         *
 *   This file is part of LuxRays.                                         *
 *                                                                         *
 *   LuxRays is free software; you can redistribute it and/or modify       *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 3 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   LuxRays 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 this program.  If not, see <http://www.gnu.org/licenses/>. *
 *                                                                         *
 *   LuxRays website: http://www.luxrender.net                             *
 ***************************************************************************/

#include <cstdio>
#include <cstdlib>

#include "smalllux.h"
#include "mainwindow.h"
#include "luxmarkapp.h"

static void PrintCmdLineHelp(const QString &cmd) {
	cerr << "Usage: " << cmd.toAscii().data() << " [options]" << endl <<
			" --help <display this help and exit>" << endl <<
			" --scene=<LUXBALL_HDR|SALA|ROOM>" << endl <<
			" --mode=<BENCHMARK_OCL_GPU|BENCHMARK_OCL_CPUGPU|BENCHMARK_OCL_CPU|INTERACTIVE|PAUSE>" << endl;
}

int main(int argc, char **argv) {
	LuxMarkApp app(argc, argv);

	// Get the arguments into a list
	bool exit = false;

	QStringList argsList = app.arguments();
	QRegExp argHelp("--help");
	QRegExp argScene("--scene=(LUXBALL_HDR|SALA|ROOM)");
	QRegExp argMode("--mode=(BENCHMARK_OCL_GPU|BENCHMARK_OCL_CPUGPU|BENCHMARK_OCL_CPU|INTERACTIVE|PAUSE)");

	LuxMarkAppMode mode = BENCHMARK_OCL_GPU;
	const char *scnName = SCENE_SALA;
    for (int i = 1; i < argsList.size(); ++i) {
        if (argHelp.indexIn(argsList.at(i)) != -1 ) {
			PrintCmdLineHelp(argsList.at(0));
            exit = true;
			break;
		} else if (argScene.indexIn(argsList.at(i)) != -1 ) {
            QString scene = argScene.cap(1);
			if (scene.compare("LUXBALL_HDR", Qt::CaseInsensitive) == 0)
				scnName = SCENE_LUXBALL_HDR;
			else if (scene.compare("SALA", Qt::CaseInsensitive) == 0)
				scnName = SCENE_SALA;
			else if (scene.compare("ROOM", Qt::CaseInsensitive) == 0)
				scnName = SCENE_ROOM;
			else {
				cerr << "Unknown scene name: " << argScene.cap(1).toAscii().data() << endl;
				PrintCmdLineHelp(argsList.at(0));
				exit = true;
				break;
			}
		} else if (argMode.indexIn(argsList.at(i)) != -1 ) {
            QString scene = argMode.cap(1);
			if (scene.compare("BENCHMARK_OCL_GPU", Qt::CaseInsensitive) == 0)
				mode = BENCHMARK_OCL_GPU;
			else if (scene.compare("BENCHMARK_OCL_CPUGPU", Qt::CaseInsensitive) == 0)
				mode = BENCHMARK_OCL_CPUGPU;
			else if (scene.compare("BENCHMARK_OCL_CPU", Qt::CaseInsensitive) == 0)
				mode = BENCHMARK_OCL_CPU;
			else if (scene.compare("INTERACTIVE", Qt::CaseInsensitive) == 0)
				mode = INTERACTIVE;
			else if (scene.compare("PAUSE", Qt::CaseInsensitive) == 0)
				mode = PAUSE;
			else {
				cerr << "Unknown mode name: " << argMode.cap(1).toAscii().data() << endl;
				PrintCmdLineHelp(argsList.at(0));
				exit = true;
				break;
			}
        } else {
            cerr << "Unknown argument: " << argsList.at(i).toAscii().data() << endl;
			PrintCmdLineHelp(argsList.at(0));
			exit = true;
			break;
        }
    }

	if (exit)
		return EXIT_SUCCESS;
	else {
		app.Init(mode, scnName);

		// Force C locale
		setlocale(LC_NUMERIC,"C");

		if (app.mainWin != NULL)
			return app.exec();
		else
			return EXIT_FAILURE;
	}
}
<|endoftext|>


<commit_before>#pragma once

#include <eosio/chain/webassembly/common.hpp>
#include <eosio/chain/webassembly/runtime_interface.hpp>
#include <eosio/chain/exceptions.hpp>
#include <eosio/chain/apply_context.hpp>
#include <softfloat_types.h>

//eos-vm includes
#include <eosio/wasm_backend/backend.hpp>

// eosio specific specializations
namespace eosio { namespace wasm_backend {
   template <>
   struct reduce_type<chain::name> {
      typedef uint64_t type;
   };

   template <typename S, typename T, typename Backend>
   constexpr auto get_value(Backend& backend, T&& val) -> std::enable_if_t<std::is_same_v<i64_const_t, T> &&
                                                          std::is_same_v<chain::name, std::decay_t<S>>, S> {
      return {(uint64_t)val.data.ui};
   }
   // we can clean these up if we go with custom vms
   template <typename T>
   struct reduce_type<eosio::chain::array_ptr<T>> {
      typedef uint32_t type;
   };

   template <typename S, typename T, typename Backend>
   constexpr auto get_value(Backend& backend, T&& val) -> std::enable_if_t<std::is_same_v<i32_const_t, T> &&
   						  std::is_same_v< eosio::chain::array_ptr<typename S::type>, S> &&
						 !std::is_lvalue_reference_v<S> && !std::is_pointer_v<S>, S> {
      return eosio::chain::array_ptr<typename S::type>((typename S::type*)(backend.get_wasm_allocator()->template get_base_ptr<uint8_t>()+val.data.ui));
   }

   template <>
   struct reduce_type<eosio::chain::null_terminated_ptr> {
      typedef uint32_t type;
   };

   template <typename S, typename T, typename Backend>
   constexpr auto get_value(Backend& backend, T&& val) -> std::enable_if_t<std::is_same_v<i32_const_t, T> &&
   						  std::is_same_v< eosio::chain::null_terminated_ptr, S> &&
						 !std::is_lvalue_reference_v<S> && !std::is_pointer_v<S>, S> {
      return eosio::chain::null_terminated_ptr((char*)(backend.get_wasm_allocator()->template get_base_ptr<uint8_t>()+val.data.ui));
   }

}} // ns eosio::wasm_backend

namespace eosio { namespace chain { namespace webassembly { namespace eos_vm_runtime {

using namespace fc;
using namespace eosio::wasm_backend;
using namespace eosio::chain::webassembly::common;

class eos_vm_runtime : public eosio::chain::wasm_runtime_interface {
   public:
      eos_vm_runtime();
      std::unique_ptr<wasm_instantiated_module_interface> instantiate_module(const char* code_bytes, size_t code_size, std::vector<uint8_t>) override;

      void immediately_exit_currently_running_module() override { _bkend->immediate_exit(); }

   private:
      backend<apply_context>* _bkend;  // non owning pointer to allow for immediate exit
};

} } } }// eosio::chain::webassembly::wabt_runtime

#define __EOS_VM_INTRINSIC_NAME(LBL, SUF) LBL##SUF
#define _EOS_VM_INTRINSIC_NAME(LBL, SUF) __INTRINSIC_NAME(LBL, SUF)

#define _REGISTER_EOS_VM_INTRINSIC(CLS, MOD, METHOD, WASM_SIG, NAME, SIG)\
   eosio::wasm_backend::registered_function<CLS, &CLS::METHOD, eosio::wasm_backend::backend<CLS>> _EOS_VM_INTRINSIC_NAME(__eos_vm_intrinsic_fn, __COUNTER__){MOD, NAME};

<commit_msg>solved issue with linking<commit_after>#pragma once

#include <eosio/chain/webassembly/common.hpp>
#include <eosio/chain/webassembly/runtime_interface.hpp>
#include <eosio/chain/exceptions.hpp>
#include <eosio/chain/apply_context.hpp>
#include <softfloat_types.h>

//eos-vm includes
#include <eosio/wasm_backend/backend.hpp>

// eosio specific specializations
namespace eosio { namespace wasm_backend {
   template <>
   struct reduce_type<chain::name> {
      typedef uint64_t type;
   };

   template <typename S, typename T, typename Backend>
   constexpr auto get_value(Backend& backend, T&& val) -> std::enable_if_t<std::is_same_v<i64_const_t, T> &&
                                                          std::is_same_v<chain::name, std::decay_t<S>>, S> {
      return {(uint64_t)val.data.ui};
   }
   // we can clean these up if we go with custom vms
   template <typename T>
   struct reduce_type<eosio::chain::array_ptr<T>> {
      typedef uint32_t type;
   };

   template <typename S, typename T, typename Backend>
   constexpr auto get_value(Backend& backend, T&& val) -> std::enable_if_t<std::is_same_v<i32_const_t, T> &&
   						  std::is_same_v< eosio::chain::array_ptr<typename S::type>, S> &&
						 !std::is_lvalue_reference_v<S> && !std::is_pointer_v<S>, S> {
      return eosio::chain::array_ptr<typename S::type>((typename S::type*)(backend.get_wasm_allocator()->template get_base_ptr<uint8_t>()+val.data.ui));
   }

   template <>
   struct reduce_type<eosio::chain::null_terminated_ptr> {
      typedef uint32_t type;
   };

   template <typename S, typename T, typename Backend>
   constexpr auto get_value(Backend& backend, T&& val) -> std::enable_if_t<std::is_same_v<i32_const_t, T> &&
   						  std::is_same_v< eosio::chain::null_terminated_ptr, S> &&
						 !std::is_lvalue_reference_v<S> && !std::is_pointer_v<S>, S> {
      return eosio::chain::null_terminated_ptr((char*)(backend.get_wasm_allocator()->template get_base_ptr<uint8_t>()+val.data.ui));
   }

}} // ns eosio::wasm_backend

namespace eosio { namespace chain { namespace webassembly { namespace eos_vm_runtime {

using namespace fc;
using namespace eosio::wasm_backend;
using namespace eosio::chain::webassembly::common;

class eos_vm_runtime : public eosio::chain::wasm_runtime_interface {
   public:
      eos_vm_runtime();
      std::unique_ptr<wasm_instantiated_module_interface> instantiate_module(const char* code_bytes, size_t code_size, std::vector<uint8_t>) override;

      void immediately_exit_currently_running_module() override { _bkend->immediate_exit(); }

   private:
      backend<apply_context>* _bkend;  // non owning pointer to allow for immediate exit
};

} } } }// eosio::chain::webassembly::wabt_runtime

#define __EOS_VM_INTRINSIC_NAME(LBL, SUF) LBL##SUF
#define _EOS_VM_INTRINSIC_NAME(LBL, SUF) __INTRINSIC_NAME(LBL, SUF)

#define _REGISTER_EOS_VM_INTRINSIC(CLS, MOD, METHOD, WASM_SIG, NAME, SIG) \
   eosio::wasm_backend::registered_function<eosio::chain::apply_context, CLS, &CLS::METHOD, eosio::wasm_backend::backend<eosio::chain::apply_context>> _EOS_VM_INTRINSIC_NAME(__eos_vm_intrinsic_fn, __COUNTER__)(std::string(MOD), std::string(NAME));

<|endoftext|>


<commit_before>/*********************************************************************
 * Software License Agreement (BSD License)
 *
 *  Copyright (c) 2008, Willow Garage, Inc.
 *  Copyright (c) 2012, hiDOF, Inc.
 *  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.
 *   * Neither the name of the Willow Garage nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 *  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 OWNER 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.
 *********************************************************************/

#include <effort_controllers/joint_position_controller.h>
#include <angles/angles.h>
#include <pluginlib/class_list_macros.h>

namespace effort_controllers {

JointPositionController::JointPositionController()
: loop_count_(0)
{}

JointPositionController::~JointPositionController()
{
  sub_command_.shutdown();
}

bool JointPositionController::init(hardware_interface::EffortJointInterface *robot,
				   const std::string &joint_name, const control_toolbox::Pid &pid)
{
  joint_ = robot->getHandle(joint_name);
  pid_controller_ = pid;

  // get urdf info about joint
  urdf::Model urdf;
  if (!urdf.initParam("robot_description")){
    ROS_ERROR("Failed to parse urdf file");
    return false;
  }
  joint_urdf_ = urdf.getJoint(joint_name);
  if (!joint_urdf_){
    ROS_ERROR("Could not find joint '%s' in urdf", joint_name.c_str());
    return false;
  }

  return true;
}

bool JointPositionController::init(hardware_interface::EffortJointInterface *robot, ros::NodeHandle &n)
{
  std::string joint_name;
  if (!n.getParam("joint", joint_name)) {
    ROS_ERROR("No joint given (namespace: %s)", n.getNamespace().c_str());
    return false;
  }

  control_toolbox::Pid pid;
  if (!pid.init(ros::NodeHandle(n, "pid")))
    return false;

  controller_state_publisher_.reset(
    new realtime_tools::RealtimePublisher<controllers_msgs::JointControllerState>(n, "state", 1));

  sub_command_ = n.subscribe<std_msgs::Float64>("command", 1, &JointPositionController::setCommandCB, this);

  return init(robot, joint_name, pid);
}

void JointPositionController::setGains(const double &p, const double &i, const double &d, const double &i_max, const double &i_min)
{
  pid_controller_.setGains(p,i,d,i_max,i_min);
}

void JointPositionController::getGains(double &p, double &i, double &d, double &i_max, double &i_min)
{
  pid_controller_.getGains(p,i,d,i_max,i_min);
}

std::string JointPositionController::getJointName()
{
  return joint_.getName();
}

// Set the joint position command
void JointPositionController::setCommand(double cmd)
{
  // the writeFromNonRT can be used in RT, if you have the guarantee that
  //  * no non-rt thread is calling the same function (we're not subscribing to ros callbacks)
  //  * there is only one single rt thread
  command_.writeFromNonRT(cmd);
}

void JointPositionController::starting(const ros::Time& time)
{
  command_.initRT(joint_.getPosition());
  pid_controller_.reset();
}

void JointPositionController::update(const ros::Time& time, const ros::Duration& period)
{
  double command = *(command_.readFromRT());

  double error;
  if (joint_urdf_->type == urdf::Joint::REVOLUTE)
  {
    angles::shortest_angular_distance_with_limits(command,
						  joint_.getPosition(),
						  joint_urdf_->limits->lower,
						  joint_urdf_->limits->upper,
						  error);
  }
  else if (joint_urdf_->type == urdf::Joint::CONTINUOUS)
  {
    error = angles::shortest_angular_distance(command, joint_.getPosition());
  }
  else //prismatic
  {
    error = command - joint_.getPosition();
  }

  // Set the PID error and compute the PID command with nonuniform
  // time step size. This also allows the user to pass in a precomputed derivative error.
  double commanded_effort = pid_controller_.computeCommand(error, joint_.getVelocity(), period); // assuming desired velocity is 0
  joint_.setCommand(commanded_effort);

  // publish state
  if (loop_count_ % 10 == 0)
  {
    if(controller_state_publisher_ && controller_state_publisher_->trylock())
    {
      controller_state_publisher_->msg_.header.stamp = time;
      controller_state_publisher_->msg_.set_point = command;
      controller_state_publisher_->msg_.process_value = joint_.getPosition();
      controller_state_publisher_->msg_.process_value_dot = joint_.getVelocity();
      controller_state_publisher_->msg_.error = error;
      controller_state_publisher_->msg_.time_step = period.toSec();
      controller_state_publisher_->msg_.command = commanded_effort;

      double dummy;
      getGains(controller_state_publisher_->msg_.p,
               controller_state_publisher_->msg_.i,
               controller_state_publisher_->msg_.d,
               controller_state_publisher_->msg_.i_clamp,
               dummy);
      controller_state_publisher_->unlockAndPublish();
    }
  }
  loop_count_++;
}

void JointPositionController::setCommandCB(const std_msgs::Float64ConstPtr& msg)
{
  setCommand(msg->data);
}

} // namespace

PLUGINLIB_EXPORT_CLASS( effort_controllers::JointPositionController, controller_interface::ControllerBase)
<commit_msg>Fixing position effort controller pid command args<commit_after>/*********************************************************************
 * Software License Agreement (BSD License)
 *
 *  Copyright (c) 2008, Willow Garage, Inc.
 *  Copyright (c) 2012, hiDOF, Inc.
 *  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.
 *   * Neither the name of the Willow Garage nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 *  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 OWNER 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.
 *********************************************************************/

#include <effort_controllers/joint_position_controller.h>
#include <angles/angles.h>
#include <pluginlib/class_list_macros.h>

namespace effort_controllers {

JointPositionController::JointPositionController()
: loop_count_(0)
{}

JointPositionController::~JointPositionController()
{
  sub_command_.shutdown();
}

bool JointPositionController::init(hardware_interface::EffortJointInterface *robot,
				   const std::string &joint_name, const control_toolbox::Pid &pid)
{
  joint_ = robot->getHandle(joint_name);
  pid_controller_ = pid;

  // get urdf info about joint
  urdf::Model urdf;
  if (!urdf.initParam("robot_description")){
    ROS_ERROR("Failed to parse urdf file");
    return false;
  }
  joint_urdf_ = urdf.getJoint(joint_name);
  if (!joint_urdf_){
    ROS_ERROR("Could not find joint '%s' in urdf", joint_name.c_str());
    return false;
  }

  return true;
}

bool JointPositionController::init(hardware_interface::EffortJointInterface *robot, ros::NodeHandle &n)
{
  std::string joint_name;
  if (!n.getParam("joint", joint_name)) {
    ROS_ERROR("No joint given (namespace: %s)", n.getNamespace().c_str());
    return false;
  }

  control_toolbox::Pid pid;
  if (!pid.init(ros::NodeHandle(n, "pid")))
    return false;

  controller_state_publisher_.reset(
    new realtime_tools::RealtimePublisher<controllers_msgs::JointControllerState>(n, "state", 1));

  sub_command_ = n.subscribe<std_msgs::Float64>("command", 1, &JointPositionController::setCommandCB, this);

  return init(robot, joint_name, pid);
}

void JointPositionController::setGains(const double &p, const double &i, const double &d, const double &i_max, const double &i_min)
{
  pid_controller_.setGains(p,i,d,i_max,i_min);
}

void JointPositionController::getGains(double &p, double &i, double &d, double &i_max, double &i_min)
{
  pid_controller_.getGains(p,i,d,i_max,i_min);
}

std::string JointPositionController::getJointName()
{
  return joint_.getName();
}

// Set the joint position command
void JointPositionController::setCommand(double cmd)
{
  // the writeFromNonRT can be used in RT, if you have the guarantee that
  //  * no non-rt thread is calling the same function (we're not subscribing to ros callbacks)
  //  * there is only one single rt thread
  command_.writeFromNonRT(cmd);
}

void JointPositionController::starting(const ros::Time& time)
{
  command_.initRT(joint_.getPosition());
  pid_controller_.reset();
}

void JointPositionController::update(const ros::Time& time, const ros::Duration& period)
{
  double command = *(command_.readFromRT());

  double error, vel_error;

  // Compute position error
  if (joint_urdf_->type == urdf::Joint::REVOLUTE)
  {
    angles::shortest_angular_distance_with_limits(command,
						  joint_.getPosition(),
						  joint_urdf_->limits->lower,
						  joint_urdf_->limits->upper,
						  error);
  }
  else if (joint_urdf_->type == urdf::Joint::CONTINUOUS)
  {
    error = angles::shortest_angular_distance(command, joint_.getPosition());
  }
  else //prismatic
  {
    error = command - joint_.getPosition();
  }

  // Compute velocity error assuming desired velocity is 0
  vel_error = 0.0 - joint_.getVelocity();

  // Set the PID error and compute the PID command with nonuniform
  // time step size. This also allows the user to pass in a precomputed derivative error.
  double commanded_effort = pid_controller_.computeCommand(error, vel_error, period);
  joint_.setCommand(commanded_effort);

  // publish state
  if (loop_count_ % 10 == 0)
  {
    if(controller_state_publisher_ && controller_state_publisher_->trylock())
    {
      controller_state_publisher_->msg_.header.stamp = time;
      controller_state_publisher_->msg_.set_point = command;
      controller_state_publisher_->msg_.process_value = joint_.getPosition();
      controller_state_publisher_->msg_.process_value_dot = joint_.getVelocity();
      controller_state_publisher_->msg_.error = error;
      controller_state_publisher_->msg_.time_step = period.toSec();
      controller_state_publisher_->msg_.command = commanded_effort;

      double dummy;
      getGains(controller_state_publisher_->msg_.p,
               controller_state_publisher_->msg_.i,
               controller_state_publisher_->msg_.d,
               controller_state_publisher_->msg_.i_clamp,
               dummy);
      controller_state_publisher_->unlockAndPublish();
    }
  }
  loop_count_++;
}

void JointPositionController::setCommandCB(const std_msgs::Float64ConstPtr& msg)
{
  setCommand(msg->data);
}

} // namespace

PLUGINLIB_EXPORT_CLASS( effort_controllers::JointPositionController, controller_interface::ControllerBase)
<|endoftext|>