<commit_before>/*
*		Event Manager by quckly.ru
*				Version: 1.1
*
*/

#include "q_events.h"

EventManager Events;

EventManager::EventManager()
{
	m_hook = false;
	//m_args = std::vector<EventArg>(16);
}

void EventManager::RegisterEvent(const int _msg_id, EventCallback _func)
{
	// Check for exist
	for (auto iter = m_regevents.cbegin(); iter != m_regevents.cend(); iter++)
		if (iter->msg_id == _msg_id && iter->func == _func)
			return;

	m_regevents.push_back(EventRegister(_msg_id, _func));
}

void EventManager::RegisterEvent(const char* msg_name, EventCallback func)
{
	RegisterEvent(ID(msg_name), func);
}

int EventManager::ID(const char* msg_name)
{
	return GET_USER_MSG_ID(PLID, msg_name, NULL);
}

// Get args
int EventManager::GetArgInt(int num)
{
	if (num < 0 || num >= m_args.size())
		return 0;

	return m_args[num].value.iValue;
}

float EventManager::GetArgFloat(int num)
{
	if (num < 0 || num >= m_args.size())
		return 0.0;

	return m_args[num].value.flValue;
}

const char* EventManager::GetArgString(int num)
{
	if (num < 0 || num >= m_args.size() || m_args[num].m_type != at_string)
		return nullptr;

	return m_args[num].str.c_str();
}

// Set Args
void EventManager::SetArg(int num, int set)
{
	if (num < 0 || num >= m_args.size())
		return;

	m_args[num].value.iValue = set;
}

void EventManager::SetArg(int num, float set)
{
	if (num < 0 || num >= m_args.size())
		return;

	m_args[num].value.flValue = set;
}

void EventManager::SetArg(int num, const char* set)
{
	if (num < 0 || num >= m_args.size() || m_args[num].m_type != at_string)
		return;

	m_args[num].str = set;
}

// Handlers
void EventManager::EM_MessageBegin(int msg_dest, int msg_type, const float *pOrigin, edict_t *ed)
{
	m_args.clear();
	m_hook = false;

	for (auto iter = m_regevents.cbegin(); iter != m_regevents.cend(); iter++)
	{
		if (msg_type == iter->msg_id)
		{
			m_hook = true;

			m_msg_dest = msg_dest;
			m_msg_type = msg_type;
			m_origin = pOrigin;
			m_ed = ed;

			RETURN_META(MRES_SUPERCEDE);
		}
	}

	RETURN_META(MRES_IGNORED);
}

void EventManager::EM_MessageEnd()
{
	if (m_hook)
	{
		m_hook = false;

		int cb_return = ER_IGNORED, _cbret;

		// Execute all registered events
		for (auto iter = m_regevents.cbegin(); iter != m_regevents.cend(); iter++)
		{
			if (m_msg_type == iter->msg_id)
			{
				_cbret = iter->func(m_msg_dest, m_msg_type, m_origin, m_ed);

				if (_cbret == ER_SUPERCEDE)
					cb_return = ER_SUPERCEDE;
			}
		}

		if (cb_return == ER_SUPERCEDE)
		{
			RETURN_META(MRES_SUPERCEDE);
		}

		// Send message
		MESSAGE_BEGIN(m_msg_dest, m_msg_type, m_origin, m_ed);

		for (auto iter = m_args.cbegin(); iter != m_args.cend(); iter++)
		{
			switch (iter->m_type)
			{
			case at_byte:
				WRITE_BYTE(iter->value.iValue);
				break;
			case at_char:
				WRITE_CHAR(iter->value.iValue);
				break;
			case at_short:
				WRITE_SHORT(iter->value.iValue);
				break;
			case at_long:
				WRITE_LONG(iter->value.iValue);
				break;
			case at_angle:
				WRITE_ANGLE(iter->value.flValue);
				break;
			case at_coord:
				WRITE_COORD(iter->value.flValue);
				break;
			case at_string:
				WRITE_STRING(iter->str.c_str());
				break;
			case at_entity:
				WRITE_ENTITY(iter->value.iValue);
				break;
			}
		}

		MESSAGE_END();

		RETURN_META(MRES_SUPERCEDE);
	}

	RETURN_META(MRES_IGNORED);
}

void EventManager::EM_WriteByte(int iValue)
{
	if (!m_hook)
		RETURN_META(MRES_IGNORED);

	m_args.push_back(EventArg(at_byte, iValue));

	RETURN_META(MRES_SUPERCEDE);
}

void EventManager::EM_WriteChar(int iValue)
{
	if (!m_hook)
		RETURN_META(MRES_IGNORED);

	m_args.push_back(EventArg(at_char, iValue));

	RETURN_META(MRES_SUPERCEDE);
}

void EventManager::EM_WriteShort(int iValue)
{
	if (!m_hook)
		RETURN_META(MRES_IGNORED);

	m_args.push_back(EventArg(at_short, iValue));

	RETURN_META(MRES_SUPERCEDE);
}

void EventManager::EM_WriteLong(int iValue)
{
	if (!m_hook)
		RETURN_META(MRES_IGNORED);

	m_args.push_back(EventArg(at_long, iValue));

	RETURN_META(MRES_SUPERCEDE);
}

void EventManager::EM_WriteAngle(float flValue)
{
	if (!m_hook)
		RETURN_META(MRES_IGNORED);

	m_args.push_back(EventArg(at_angle, flValue));

	RETURN_META(MRES_SUPERCEDE);
}

void EventManager::EM_WriteCoord(float flValue)
{
	if (!m_hook)
		RETURN_META(MRES_IGNORED);

	m_args.push_back(EventArg(at_coord, flValue));

	RETURN_META(MRES_SUPERCEDE);
}

void EventManager::EM_WriteString(const char *sz)
{
	if (!m_hook)
		RETURN_META(MRES_IGNORED);

	m_args.push_back(EventArg(at_string, sz));

	RETURN_META(MRES_SUPERCEDE);
}

void EventManager::EM_WriteEntity(int iValue)
{
	if (!m_hook)
		RETURN_META(MRES_IGNORED);

	m_args.push_back(EventArg(at_entity, iValue));

	RETURN_META(MRES_SUPERCEDE);
}<commit_msg>Fixed SUPERCEDE return in EventManager<commit_after>/*
*		Event Manager by quckly
*				Version: 1.0
*
*/

#include "q_events.h"

EventManager Events;

EventManager::EventManager()
{
	m_hook = false;
	//m_args = std::vector<EventArg>(16);
}

void EventManager::RegisterEvent(const int _msg_id, EventCallback _func)
{
	// Check for exist
	for (auto iter = m_regevents.cbegin(); iter != m_regevents.cend(); iter++)
		if (iter->msg_id == _msg_id && iter->func == _func)
			return;

	m_regevents.push_back(EventRegister(_msg_id, _func));
}

void EventManager::RegisterEvent(const char* msg_name, EventCallback func)
{
	RegisterEvent(ID(msg_name), func);
}

int EventManager::ID(const char* msg_name)
{
	return GET_USER_MSG_ID(PLID, msg_name, NULL);
}

// Get args
int EventManager::GetArgInt(int num)
{
	if (num < 0 || num >= m_args.size())
		return 0;

	return m_args[num].value.iValue;
}

float EventManager::GetArgFloat(int num)
{
	if (num < 0 || num >= m_args.size())
		return 0.0;

	return m_args[num].value.flValue;
}

const char* EventManager::GetArgString(int num)
{
	if (num < 0 || num >= m_args.size() || m_args[num].m_type != at_string)
		return nullptr;

	return m_args[num].str.c_str();
}

// Set Args
void EventManager::SetArg(int num, int set)
{
	if (num < 0 || num >= m_args.size())
		return;

	m_args[num].value.iValue = set;
}

void EventManager::SetArg(int num, float set)
{
	if (num < 0 || num >= m_args.size())
		return;

	m_args[num].value.flValue = set;
}

void EventManager::SetArg(int num, const char* set)
{
	if (num < 0 || num >= m_args.size() || m_args[num].m_type != at_string)
		return;

	m_args[num].str = set;
}

// Handlers
void EventManager::EM_MessageBegin(int msg_dest, int msg_type, const float *pOrigin, edict_t *ed)
{
	m_hook = false;

	for (auto iter = m_regevents.cbegin(); iter != m_regevents.cend(); iter++)
	{
		if (msg_type == iter->msg_id)
		{
			m_hook = true;
			m_args.clear();

			m_msg_dest = msg_dest;
			m_msg_type = msg_type;
			m_origin = pOrigin;
			m_ed = ed;

			RETURN_META(MRES_SUPERCEDE);
		}
	}

	RETURN_META(MRES_IGNORED);
}

void EventManager::EM_MessageEnd()
{
	if (m_hook)
	{
		m_hook = false;

		int cb_return = ER_IGNORED, _cbret;

		// Execute all registered events
		for (auto iter = m_regevents.cbegin(); iter != m_regevents.cend(); iter++)
		{
			if (m_msg_type == iter->msg_id)
			{
				_cbret = iter->func(m_msg_dest, m_msg_type, m_origin, m_ed);

				if (_cbret == ER_SUPERCEDE)
					cb_return = ER_SUPERCEDE;
			}
		}

		if (cb_return == ER_SUPERCEDE)
		{
			RETURN_META(MRES_SUPERCEDE);
		}

		// Send message
		MESSAGE_BEGIN(m_msg_dest, m_msg_type, m_origin, m_ed);

		for (auto iter = m_args.cbegin(); iter != m_args.cend(); iter++)
		{
			switch (iter->m_type)
			{
			case at_byte:
				WRITE_BYTE(iter->value.iValue);
				break;
			case at_char:
				WRITE_CHAR(iter->value.iValue);
				break;
			case at_short:
				WRITE_SHORT(iter->value.iValue);
				break;
			case at_long:
				WRITE_LONG(iter->value.iValue);
				break;
			case at_angle:
				WRITE_ANGLE(iter->value.flValue);
				break;
			case at_coord:
				WRITE_COORD(iter->value.flValue);
				break;
			case at_string:
				WRITE_STRING(iter->str.c_str());
				break;
			case at_entity:
				WRITE_ENTITY(iter->value.iValue);
				break;
			}
		}

		MESSAGE_END();

		RETURN_META(MRES_SUPERCEDE);
	}

	RETURN_META(MRES_IGNORED);
}

void EventManager::EM_WriteByte(int iValue)
{
	if (!m_hook)
		RETURN_META(MRES_IGNORED);

	m_args.push_back(EventArg(at_byte, iValue));

	RETURN_META(MRES_SUPERCEDE);
}

void EventManager::EM_WriteChar(int iValue)
{
	if (!m_hook)
		RETURN_META(MRES_IGNORED);

	m_args.push_back(EventArg(at_char, iValue));

	RETURN_META(MRES_SUPERCEDE);
}

void EventManager::EM_WriteShort(int iValue)
{
	if (!m_hook)
		RETURN_META(MRES_IGNORED);

	m_args.push_back(EventArg(at_short, iValue));

	RETURN_META(MRES_SUPERCEDE);
}

void EventManager::EM_WriteLong(int iValue)
{
	if (!m_hook)
		RETURN_META(MRES_IGNORED);

	m_args.push_back(EventArg(at_long, iValue));

	RETURN_META(MRES_SUPERCEDE);
}

void EventManager::EM_WriteAngle(float flValue)
{
	if (!m_hook)
		RETURN_META(MRES_IGNORED);

	m_args.push_back(EventArg(at_angle, flValue));

	RETURN_META(MRES_SUPERCEDE);
}

void EventManager::EM_WriteCoord(float flValue)
{
	if (!m_hook)
		RETURN_META(MRES_IGNORED);

	m_args.push_back(EventArg(at_coord, flValue));

	RETURN_META(MRES_SUPERCEDE);
}

void EventManager::EM_WriteString(const char *sz)
{
	if (!m_hook)
		RETURN_META(MRES_IGNORED);

	m_args.push_back(EventArg(at_string, sz));

	RETURN_META(MRES_SUPERCEDE);
}

void EventManager::EM_WriteEntity(int iValue)
{
	if (!m_hook)
		RETURN_META(MRES_IGNORED);

	m_args.push_back(EventArg(at_entity, iValue));

	RETURN_META(MRES_SUPERCEDE);
}<|endoftext|>


<commit_before>/*//////////////////////////////////////////////////////////////////
////       SKIRT -- an advanced radiative transfer code         ////
////       © Astronomical Observatory, Ghent University         ////
///////////////////////////////////////////////////////////////// */

#ifdef BUILDING_WITH_MPI
#include <mpi.h>
#endif

#include "ProcessManager.hpp"

#include <exception>
#include <QDataStream>

////////////////////////////////////////////////////////////////////

#ifdef BUILDING_WITH_MPI
namespace
{
    // When an Array with more than INT_MAX elements is to be communicated,
    // the message will be broken up into pieces of the following size
    const int maxMessageSize = 2000000000;

    // Creates (and commits!) a datatype consisting of blocks of a certain length, displaced according to a list of
    // displacements in units of the block length. The created datatype should be freed when it is no longer needed.
    void createDisplacedDoubleBlocks(size_t blocklength, const std::vector<int>& displacements,
                                     MPI_Datatype* newtypeP, size_t extent = 0)
    {
        size_t count = displacements.size();

        // These are passed to int arguments of MPI functions, so we need to check for a possible integer overflow
        if (blocklength > INT_MAX) throw std::overflow_error("blocklength larger than INT_MAX");
        if (count > INT_MAX) throw std::overflow_error("number of elements larger than INT_MAX");

        // Intermediary datatype (counting by double causes overflow when displacements[i]*blocklength > INT_MAX)
        MPI_Datatype singleBlock;
        MPI_Type_contiguous(blocklength, MPI_DOUBLE, &singleBlock);

        // Create a datatype representing a structure of displaced blocks of the same size;
        MPI_Datatype indexedBlock;
        MPI_Type_create_indexed_block(count, 1, displacements.data(), singleBlock, &indexedBlock);

        if (extent != 0)
        {
            // Pad this datatype to modify the extent to the requested value
            MPI_Aint lb;
            MPI_Aint ex;
            MPI_Type_get_extent(indexedBlock, &lb, &ex);
            MPI_Type_create_resized(indexedBlock, lb, extent*sizeof(double), newtypeP);

            // Commit the final type and free the intermediary one
            MPI_Type_commit(newtypeP);
            MPI_Type_free(&indexedBlock);
        }
        else
        {
            // No padding, just store the indexed block
            *newtypeP = indexedBlock;
            MPI_Type_commit(newtypeP);
        }

        // Free the intermediary type
        MPI_Type_free(&singleBlock);
    }
}
#endif

std::atomic<int> ProcessManager::requests(0);

//////////////////////////////////////////////////////////////////////

void ProcessManager::initialize(int *argc, char ***argv)
{
#ifdef BUILDING_WITH_MPI
    int initialized;
    MPI_Initialized(&initialized);
    if (!initialized)
    {
        MPI_Init(argc, argv);
    }
#else
    Q_UNUSED(argc) Q_UNUSED(argv)
#endif
}

//////////////////////////////////////////////////////////////////////

void ProcessManager::finalize()
{
#ifdef BUILDING_WITH_MPI
    MPI_Finalize();
#endif
}

//////////////////////////////////////////////////////////////////////

void ProcessManager::acquireMPI(int& rank, int& Nprocs)
{
#ifdef BUILDING_WITH_MPI
    int oldrequests = requests++;

    if (oldrequests) // if requests >=1
    {
        Nprocs = 1;
        rank = 0;
    }
    else // requests == 0
    {
        MPI_Comm_size(MPI_COMM_WORLD, &Nprocs);
        MPI_Comm_rank(MPI_COMM_WORLD, &rank);
    }
#else
    rank = 0;
    Nprocs = 1;
#endif
}

//////////////////////////////////////////////////////////////////////

void ProcessManager::releaseMPI()
{
#ifdef BUILDING_WITH_MPI
    requests--;
#endif
}

//////////////////////////////////////////////////////////////////////

void ProcessManager::barrier()
{
#ifdef BUILDING_WITH_MPI
    MPI_Barrier(MPI_COMM_WORLD);
#endif
}

//////////////////////////////////////////////////////////////////////

void ProcessManager::sendByteBuffer(QByteArray& buffer, int receiver, int tag)
{
#ifdef BUILDING_WITH_MPI
    MPI_Send(buffer.data(), buffer.size(), MPI_BYTE, receiver, tag, MPI_COMM_WORLD);
#else
    Q_UNUSED(buffer) Q_UNUSED(receiver) Q_UNUSED(tag)
#endif
}

//////////////////////////////////////////////////////////////////////

void ProcessManager::receiveByteBuffer(QByteArray& buffer, int& sender)
{
#ifdef BUILDING_WITH_MPI
    MPI_Status status;
    MPI_Recv(buffer.data(), buffer.size(), MPI_BYTE, MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &status);
    sender = status.MPI_SOURCE;
#else
    Q_UNUSED(buffer) Q_UNUSED(sender)
#endif
}

//////////////////////////////////////////////////////////////////////

void ProcessManager::receiveByteBuffer(QByteArray &buffer, int sender, int& tag)
{
#ifdef BUILDING_WITH_MPI
    MPI_Status status;
    MPI_Recv(buffer.data(), buffer.size(), MPI_BYTE, sender, MPI_ANY_TAG, MPI_COMM_WORLD, &status);
    tag = status.MPI_TAG;
#else
    Q_UNUSED(buffer) Q_UNUSED(sender) Q_UNUSED(tag)
#endif
}

//////////////////////////////////////////////////////////////////////

void ProcessManager::gatherw(const double* sendBuffer, size_t sendCount,
                             double* recvBuffer, int recvRank, size_t recvLength,
                             const std::vector<std::vector<int>>& recvDisplacements)
{
#ifdef BUILDING_WITH_MPI
    int size;
    int rank;
    MPI_Comm_size(MPI_COMM_WORLD, &size);
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);

    // parameters for the senders
    std::vector<int> sendcnts(size, 0);                     // every process sends nothing to all processes
    sendcnts[recvRank] = sendCount;                         // except to the receiver
    std::vector<int> sdispls(size, 0);                      // starting from sendBuffer + 0
    std::vector<MPI_Datatype> sendtypes(size, MPI_DOUBLE);  // all doubles

    // parameters on the receiving end
    std::vector<int> recvcnts;
    if (rank != recvRank) recvcnts.resize(size, 0); // I am not receiver: receive nothing from every process
    else recvcnts.resize(size, 1);                  // I am receiver: receive 1 from every process
    std::vector<int> rdispls(size, 0);              // displacements will be contained in the datatypes
    std::vector<MPI_Datatype> recvtypes;            // we will construct a derived datatype per process for receiving
    recvtypes.reserve(size);

    for (int r=0; r<size; r++)
    {
        MPI_Datatype newtype;
        createDisplacedDoubleBlocks(recvLength, recvDisplacements[r], &newtype);
        recvtypes.push_back(newtype);
    }

    MPI_Alltoallw(const_cast<double*>(sendBuffer), sendcnts.data(), sdispls.data(), sendtypes.data(),
                  recvBuffer, recvcnts.data(), rdispls.data(), recvtypes.data(),
                  MPI_COMM_WORLD);

    for (int rank=0; rank<size; rank++) MPI_Type_free(&recvtypes[rank]);
#else
    Q_UNUSED(sendBuffer) Q_UNUSED(sendCount) Q_UNUSED(recvBuffer) Q_UNUSED(recvRank) Q_UNUSED(recvLength)
    Q_UNUSED(recvDisplacements)
#endif
}

//////////////////////////////////////////////////////////////////////

void ProcessManager::displacedBlocksAllToAll(const double* sendBuffer, size_t sendCount, size_t sendLength,
                                             const std::vector<std::vector<int>>& sendDisplacements,
                                             size_t sendExtent, double* recvBuffer, size_t recvCount, size_t recvLength,
                                             const std::vector<std::vector<int>>& recvDisplacements,
                                             size_t recvExtent)
{
#ifdef BUILDING_WITH_MPI
    int size;
    MPI_Comm_size(MPI_COMM_WORLD, &size);

    std::vector<int> sendcnts(size,sendCount);
    std::vector<int> sdispls(size, 0);
    std::vector<MPI_Datatype> sendtypes;
    sendtypes.reserve(size);

    std::vector<int> recvcnts(size, recvCount);
    std::vector<int> rdispls(size, 0);
    std::vector<MPI_Datatype> recvtypes;
    recvtypes.reserve(size);

    for (int r=0; r<size; r++)
    {
        MPI_Datatype newtype;
        createDisplacedDoubleBlocks(sendLength, sendDisplacements[r], &newtype, sendExtent);
        sendtypes.push_back(newtype);

        createDisplacedDoubleBlocks(recvLength, recvDisplacements[r], &newtype, recvExtent);
        recvtypes.push_back(newtype);
    }

    MPI_Alltoallw(const_cast<double*>(sendBuffer), sendcnts.data(), sdispls.data(), sendtypes.data(),
                  recvBuffer, recvcnts.data(), rdispls.data(), recvtypes.data(),
                  MPI_COMM_WORLD);

    for (int r=0; r<size; r++)
    {
        MPI_Type_free(&sendtypes[r]);
        MPI_Type_free(&recvtypes[r]);
    }
#else
    Q_UNUSED(sendBuffer) Q_UNUSED(sendCount) Q_UNUSED(sendDisplacements) Q_UNUSED(sendLength) Q_UNUSED(sendExtent)
    Q_UNUSED(recvBuffer) Q_UNUSED(recvCount) Q_UNUSED(recvDisplacements) Q_UNUSED(recvLength) Q_UNUSED(recvExtent)
#endif
}

//////////////////////////////////////////////////////////////////////

void ProcessManager::sum(double* my_array, size_t nvalues, int root)
{
#ifdef BUILDING_WITH_MPI
    int rank;
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);

    const int maxMessageSize = 2000000000;
    size_t remaining = nvalues;
    double* my_array_position = my_array;

    while (remaining >= INT_MAX)
    {
        if (rank == root)
            MPI_Reduce(MPI_IN_PLACE, my_array_position, maxMessageSize, MPI_DOUBLE, MPI_SUM, root, MPI_COMM_WORLD);
        else
            MPI_Reduce(my_array_position, my_array_position, maxMessageSize, MPI_DOUBLE, MPI_SUM, root, MPI_COMM_WORLD);

        remaining -= maxMessageSize;
        my_array_position += maxMessageSize;
    }
    if (rank == root)
        MPI_Reduce(MPI_IN_PLACE, my_array_position, remaining, MPI_DOUBLE, MPI_SUM, root, MPI_COMM_WORLD);
    else
        MPI_Reduce(my_array_position, my_array_position, remaining, MPI_DOUBLE, MPI_SUM, root, MPI_COMM_WORLD);
#else
    Q_UNUSED(my_array) Q_UNUSED(nvalues) Q_UNUSED(root)
#endif
}

//////////////////////////////////////////////////////////////////////

void ProcessManager::sum_all(double* my_array, size_t nvalues)
{
#ifdef BUILDING_WITH_MPI
    size_t remaining = nvalues;
    while (remaining >= INT_MAX)
    {
        MPI_Allreduce(MPI_IN_PLACE, my_array + (nvalues-remaining), maxMessageSize, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
        remaining -= maxMessageSize;
    }
    MPI_Allreduce(MPI_IN_PLACE, my_array + (nvalues-remaining), remaining, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
#else
    Q_UNUSED(my_array) Q_UNUSED(nvalues)
#endif
}

//////////////////////////////////////////////////////////////////////

void ProcessManager::or_all(bool* boolean)
{
#ifdef BUILDING_WITH_MPI
    MPI_Allreduce(MPI_IN_PLACE, boolean, 1, MPI_C_BOOL, MPI_LOR, MPI_COMM_WORLD);
#else
    Q_UNUSED(boolean)
#endif
}

//////////////////////////////////////////////////////////////////////

void ProcessManager::broadcast(double* my_array, size_t nvalues, int root)
{
#ifdef BUILDING_WITH_MPI
    size_t remaining = nvalues;
    while (remaining >= INT_MAX)
    {
        MPI_Bcast(my_array + (nvalues-remaining), maxMessageSize, MPI_DOUBLE, root, MPI_COMM_WORLD);
        remaining -= maxMessageSize;
    }
    MPI_Bcast(my_array + (nvalues-remaining), remaining, MPI_DOUBLE, root, MPI_COMM_WORLD);
#else
    Q_UNUSED(my_array) Q_UNUSED(nvalues) Q_UNUSED(root)
#endif
}

//////////////////////////////////////////////////////////////////////

void ProcessManager::broadcast(int* value, int root)
{
#ifdef BUILDING_WITH_MPI
    MPI_Bcast(value, 1, MPI_INT, root, MPI_COMM_WORLD);
#else
    Q_UNUSED(value) Q_UNUSED(root)
#endif
}

//////////////////////////////////////////////////////////////////////

bool ProcessManager::isRoot()
{
#ifdef BUILDING_WITH_MPI
    int rank;
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
    return (rank == 0);
#else
    return true;
#endif
}

//////////////////////////////////////////////////////////////////////

bool ProcessManager::isMultiProc()
{
#ifdef BUILDING_WITH_MPI
    int size;
    MPI_Comm_size(MPI_COMM_WORLD, &size);
    return (size > 1);
#else
    return false;
#endif
}
<commit_msg>Cast const away for list of displacements for same reason<commit_after>/*//////////////////////////////////////////////////////////////////
////       SKIRT -- an advanced radiative transfer code         ////
////       © Astronomical Observatory, Ghent University         ////
///////////////////////////////////////////////////////////////// */

#ifdef BUILDING_WITH_MPI
#include <mpi.h>
#endif

#include "ProcessManager.hpp"

#include <exception>
#include <QDataStream>

////////////////////////////////////////////////////////////////////

#ifdef BUILDING_WITH_MPI
namespace
{
    // When an Array with more than INT_MAX elements is to be communicated,
    // the message will be broken up into pieces of the following size
    const int maxMessageSize = 2000000000;

    // Creates (and commits!) a datatype consisting of blocks of a certain length, displaced according to a list of
    // displacements in units of the block length. The created datatype should be freed when it is no longer needed.
    void createDisplacedDoubleBlocks(size_t blocklength, const std::vector<int>& displacements,
                                     MPI_Datatype* newtypeP, size_t extent = 0)
    {
        size_t count = displacements.size();

        // These are passed to int arguments of MPI functions, so we need to check for a possible integer overflow
        if (blocklength > INT_MAX) throw std::overflow_error("blocklength larger than INT_MAX");
        if (count > INT_MAX) throw std::overflow_error("number of elements larger than INT_MAX");

        // Intermediary datatype (counting by double causes overflow when displacements[i]*blocklength > INT_MAX)
        MPI_Datatype singleBlock;
        MPI_Type_contiguous(blocklength, MPI_DOUBLE, &singleBlock);

        // Create a datatype representing a structure of displaced blocks of the same size;
        MPI_Datatype indexedBlock;
        MPI_Type_create_indexed_block(count, 1, const_cast<int*>(displacements.data()), singleBlock, &indexedBlock);

        if (extent != 0)
        {
            // Pad this datatype to modify the extent to the requested value
            MPI_Aint lb;
            MPI_Aint ex;
            MPI_Type_get_extent(indexedBlock, &lb, &ex);
            MPI_Type_create_resized(indexedBlock, lb, extent*sizeof(double), newtypeP);

            // Commit the final type and free the intermediary one
            MPI_Type_commit(newtypeP);
            MPI_Type_free(&indexedBlock);
        }
        else
        {
            // No padding, just store the indexed block
            *newtypeP = indexedBlock;
            MPI_Type_commit(newtypeP);
        }

        // Free the intermediary type
        MPI_Type_free(&singleBlock);
    }
}
#endif

std::atomic<int> ProcessManager::requests(0);

//////////////////////////////////////////////////////////////////////

void ProcessManager::initialize(int *argc, char ***argv)
{
#ifdef BUILDING_WITH_MPI
    int initialized;
    MPI_Initialized(&initialized);
    if (!initialized)
    {
        MPI_Init(argc, argv);
    }
#else
    Q_UNUSED(argc) Q_UNUSED(argv)
#endif
}

//////////////////////////////////////////////////////////////////////

void ProcessManager::finalize()
{
#ifdef BUILDING_WITH_MPI
    MPI_Finalize();
#endif
}

//////////////////////////////////////////////////////////////////////

void ProcessManager::acquireMPI(int& rank, int& Nprocs)
{
#ifdef BUILDING_WITH_MPI
    int oldrequests = requests++;

    if (oldrequests) // if requests >=1
    {
        Nprocs = 1;
        rank = 0;
    }
    else // requests == 0
    {
        MPI_Comm_size(MPI_COMM_WORLD, &Nprocs);
        MPI_Comm_rank(MPI_COMM_WORLD, &rank);
    }
#else
    rank = 0;
    Nprocs = 1;
#endif
}

//////////////////////////////////////////////////////////////////////

void ProcessManager::releaseMPI()
{
#ifdef BUILDING_WITH_MPI
    requests--;
#endif
}

//////////////////////////////////////////////////////////////////////

void ProcessManager::barrier()
{
#ifdef BUILDING_WITH_MPI
    MPI_Barrier(MPI_COMM_WORLD);
#endif
}

//////////////////////////////////////////////////////////////////////

void ProcessManager::sendByteBuffer(QByteArray& buffer, int receiver, int tag)
{
#ifdef BUILDING_WITH_MPI
    MPI_Send(buffer.data(), buffer.size(), MPI_BYTE, receiver, tag, MPI_COMM_WORLD);
#else
    Q_UNUSED(buffer) Q_UNUSED(receiver) Q_UNUSED(tag)
#endif
}

//////////////////////////////////////////////////////////////////////

void ProcessManager::receiveByteBuffer(QByteArray& buffer, int& sender)
{
#ifdef BUILDING_WITH_MPI
    MPI_Status status;
    MPI_Recv(buffer.data(), buffer.size(), MPI_BYTE, MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &status);
    sender = status.MPI_SOURCE;
#else
    Q_UNUSED(buffer) Q_UNUSED(sender)
#endif
}

//////////////////////////////////////////////////////////////////////

void ProcessManager::receiveByteBuffer(QByteArray &buffer, int sender, int& tag)
{
#ifdef BUILDING_WITH_MPI
    MPI_Status status;
    MPI_Recv(buffer.data(), buffer.size(), MPI_BYTE, sender, MPI_ANY_TAG, MPI_COMM_WORLD, &status);
    tag = status.MPI_TAG;
#else
    Q_UNUSED(buffer) Q_UNUSED(sender) Q_UNUSED(tag)
#endif
}

//////////////////////////////////////////////////////////////////////

void ProcessManager::gatherw(const double* sendBuffer, size_t sendCount,
                             double* recvBuffer, int recvRank, size_t recvLength,
                             const std::vector<std::vector<int>>& recvDisplacements)
{
#ifdef BUILDING_WITH_MPI
    int size;
    int rank;
    MPI_Comm_size(MPI_COMM_WORLD, &size);
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);

    // parameters for the senders
    std::vector<int> sendcnts(size, 0);                     // every process sends nothing to all processes
    sendcnts[recvRank] = sendCount;                         // except to the receiver
    std::vector<int> sdispls(size, 0);                      // starting from sendBuffer + 0
    std::vector<MPI_Datatype> sendtypes(size, MPI_DOUBLE);  // all doubles

    // parameters on the receiving end
    std::vector<int> recvcnts;
    if (rank != recvRank) recvcnts.resize(size, 0); // I am not receiver: receive nothing from every process
    else recvcnts.resize(size, 1);                  // I am receiver: receive 1 from every process
    std::vector<int> rdispls(size, 0);              // displacements will be contained in the datatypes
    std::vector<MPI_Datatype> recvtypes;            // we will construct a derived datatype per process for receiving
    recvtypes.reserve(size);

    for (int r=0; r<size; r++)
    {
        MPI_Datatype newtype;
        createDisplacedDoubleBlocks(recvLength, recvDisplacements[r], &newtype);
        recvtypes.push_back(newtype);
    }

    MPI_Alltoallw(const_cast<double*>(sendBuffer), sendcnts.data(), sdispls.data(), sendtypes.data(),
                  recvBuffer, recvcnts.data(), rdispls.data(), recvtypes.data(),
                  MPI_COMM_WORLD);

    for (int rank=0; rank<size; rank++) MPI_Type_free(&recvtypes[rank]);
#else
    Q_UNUSED(sendBuffer) Q_UNUSED(sendCount) Q_UNUSED(recvBuffer) Q_UNUSED(recvRank) Q_UNUSED(recvLength)
    Q_UNUSED(recvDisplacements)
#endif
}

//////////////////////////////////////////////////////////////////////

void ProcessManager::displacedBlocksAllToAll(const double* sendBuffer, size_t sendCount, size_t sendLength,
                                             const std::vector<std::vector<int>>& sendDisplacements,
                                             size_t sendExtent, double* recvBuffer, size_t recvCount, size_t recvLength,
                                             const std::vector<std::vector<int>>& recvDisplacements,
                                             size_t recvExtent)
{
#ifdef BUILDING_WITH_MPI
    int size;
    MPI_Comm_size(MPI_COMM_WORLD, &size);

    std::vector<int> sendcnts(size,sendCount);
    std::vector<int> sdispls(size, 0);
    std::vector<MPI_Datatype> sendtypes;
    sendtypes.reserve(size);

    std::vector<int> recvcnts(size, recvCount);
    std::vector<int> rdispls(size, 0);
    std::vector<MPI_Datatype> recvtypes;
    recvtypes.reserve(size);

    for (int r=0; r<size; r++)
    {
        MPI_Datatype newtype;
        createDisplacedDoubleBlocks(sendLength, sendDisplacements[r], &newtype, sendExtent);
        sendtypes.push_back(newtype);

        createDisplacedDoubleBlocks(recvLength, recvDisplacements[r], &newtype, recvExtent);
        recvtypes.push_back(newtype);
    }

    MPI_Alltoallw(const_cast<double*>(sendBuffer), sendcnts.data(), sdispls.data(), sendtypes.data(),
                  recvBuffer, recvcnts.data(), rdispls.data(), recvtypes.data(),
                  MPI_COMM_WORLD);

    for (int r=0; r<size; r++)
    {
        MPI_Type_free(&sendtypes[r]);
        MPI_Type_free(&recvtypes[r]);
    }
#else
    Q_UNUSED(sendBuffer) Q_UNUSED(sendCount) Q_UNUSED(sendDisplacements) Q_UNUSED(sendLength) Q_UNUSED(sendExtent)
    Q_UNUSED(recvBuffer) Q_UNUSED(recvCount) Q_UNUSED(recvDisplacements) Q_UNUSED(recvLength) Q_UNUSED(recvExtent)
#endif
}

//////////////////////////////////////////////////////////////////////

void ProcessManager::sum(double* my_array, size_t nvalues, int root)
{
#ifdef BUILDING_WITH_MPI
    int rank;
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);

    const int maxMessageSize = 2000000000;
    size_t remaining = nvalues;
    double* my_array_position = my_array;

    while (remaining >= INT_MAX)
    {
        if (rank == root)
            MPI_Reduce(MPI_IN_PLACE, my_array_position, maxMessageSize, MPI_DOUBLE, MPI_SUM, root, MPI_COMM_WORLD);
        else
            MPI_Reduce(my_array_position, my_array_position, maxMessageSize, MPI_DOUBLE, MPI_SUM, root, MPI_COMM_WORLD);

        remaining -= maxMessageSize;
        my_array_position += maxMessageSize;
    }
    if (rank == root)
        MPI_Reduce(MPI_IN_PLACE, my_array_position, remaining, MPI_DOUBLE, MPI_SUM, root, MPI_COMM_WORLD);
    else
        MPI_Reduce(my_array_position, my_array_position, remaining, MPI_DOUBLE, MPI_SUM, root, MPI_COMM_WORLD);
#else
    Q_UNUSED(my_array) Q_UNUSED(nvalues) Q_UNUSED(root)
#endif
}

//////////////////////////////////////////////////////////////////////

void ProcessManager::sum_all(double* my_array, size_t nvalues)
{
#ifdef BUILDING_WITH_MPI
    size_t remaining = nvalues;
    while (remaining >= INT_MAX)
    {
        MPI_Allreduce(MPI_IN_PLACE, my_array + (nvalues-remaining), maxMessageSize, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
        remaining -= maxMessageSize;
    }
    MPI_Allreduce(MPI_IN_PLACE, my_array + (nvalues-remaining), remaining, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
#else
    Q_UNUSED(my_array) Q_UNUSED(nvalues)
#endif
}

//////////////////////////////////////////////////////////////////////

void ProcessManager::or_all(bool* boolean)
{
#ifdef BUILDING_WITH_MPI
    MPI_Allreduce(MPI_IN_PLACE, boolean, 1, MPI_C_BOOL, MPI_LOR, MPI_COMM_WORLD);
#else
    Q_UNUSED(boolean)
#endif
}

//////////////////////////////////////////////////////////////////////

void ProcessManager::broadcast(double* my_array, size_t nvalues, int root)
{
#ifdef BUILDING_WITH_MPI
    size_t remaining = nvalues;
    while (remaining >= INT_MAX)
    {
        MPI_Bcast(my_array + (nvalues-remaining), maxMessageSize, MPI_DOUBLE, root, MPI_COMM_WORLD);
        remaining -= maxMessageSize;
    }
    MPI_Bcast(my_array + (nvalues-remaining), remaining, MPI_DOUBLE, root, MPI_COMM_WORLD);
#else
    Q_UNUSED(my_array) Q_UNUSED(nvalues) Q_UNUSED(root)
#endif
}

//////////////////////////////////////////////////////////////////////

void ProcessManager::broadcast(int* value, int root)
{
#ifdef BUILDING_WITH_MPI
    MPI_Bcast(value, 1, MPI_INT, root, MPI_COMM_WORLD);
#else
    Q_UNUSED(value) Q_UNUSED(root)
#endif
}

//////////////////////////////////////////////////////////////////////

bool ProcessManager::isRoot()
{
#ifdef BUILDING_WITH_MPI
    int rank;
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
    return (rank == 0);
#else
    return true;
#endif
}

//////////////////////////////////////////////////////////////////////

bool ProcessManager::isMultiProc()
{
#ifdef BUILDING_WITH_MPI
    int size;
    MPI_Comm_size(MPI_COMM_WORLD, &size);
    return (size > 1);
#else
    return false;
#endif
}
<|endoftext|>


<commit_before>// -------------------------------------------------------------------------
//    @FileName         :    NFCProperty.cpp
//    @Author           :    LvSheng.Huang
//    @Date             :    2012-03-01
//    @Module           :    NFCProperty
//
// -------------------------------------------------------------------------

#include "NFCProperty.h"
#include <complex>

NFCProperty::NFCProperty()
{
    mbPublic = false;
    mbPrivate = false;
    mbSave = false;
    mSelf = NFGUID();
    eType = TDATA_UNKNOWN;

    msPropertyName = "";
}

NFCProperty::NFCProperty(const NFGUID& self, const std::string& strPropertyName, const TDATA_TYPE varType, bool bPublic,  bool bPrivate,  bool bSave, const std::string& strRelationValue)
{

    mbPublic = bPublic;
    mbPrivate = bPrivate;
    mbSave = bSave;
    mSelf = self;

    msPropertyName = strPropertyName;
    mstrRelationValue = strRelationValue;
    eType = varType;
}

NFCProperty::~NFCProperty()
{
    for (TPROPERTYCALLBACKEX::iterator iter = mtPropertyCallback.begin(); iter != mtPropertyCallback.end(); ++iter)
    {
        iter->reset();
    }

    mtPropertyCallback.clear();
    mxData.reset();
}

void NFCProperty::SetValue(const NFIDataList::TData& TData)
{
    if (eType != TData.GetType())
    {
        return;
    }

    if (!mxData.get())
    {
        if (!TData.IsNullValue())
        {
            return;
        }

        mxData = NF_SHARE_PTR<NFIDataList::TData>(NF_NEW NFIDataList::TData(TData));
    }

    NFCDataList::TData oldValue;
    oldValue = *mxData;

    mxData->variantData = TData.variantData;

    NFCDataList::TData newValue;
    newValue = *mxData;

    OnEventHandler(oldValue , newValue);
}

void NFCProperty::SetValue(const NFIProperty* pProperty)
{
    SetValue(pProperty->GetValue());
}

const NFIDataList::TData& NFCProperty::GetValue() const
{
    if (mxData.get())
    {
        return *mxData;
    }

    return NULL_TDATA;
}

const std::string&  NFCProperty::GetKey() const
{
    return msPropertyName;
}

const bool NFCProperty::GetSave() const
{
    return mbSave;
}

const bool NFCProperty::GetPublic() const
{
    return mbPublic;
}

const bool NFCProperty::GetPrivate() const
{
    return mbPrivate;
}

const std::string& NFCProperty::GetRelationValue() const
{
    return mstrRelationValue;
}

void NFCProperty::SetSave(bool bSave)
{
    mbSave = bSave;
}

void NFCProperty::SetPublic(bool bPublic)
{
    mbPublic = bPublic;
}

void NFCProperty::SetPrivate(bool bPrivate)
{
    mbPrivate = bPrivate;
}

void NFCProperty::SetRelationValue(const std::string& strRelationValue)
{
    mstrRelationValue = strRelationValue;
}

NFINT64 NFCProperty::GetInt() const
{
    if (!mxData.get())
    {
        return 0;
    }

    return mxData->GetInt();
}

double NFCProperty::GetFloat() const
{
    if (!mxData.get())
    {
        return 0.0;
    }

    return mxData->GetFloat();
}

const std::string& NFCProperty::GetString() const
{
    if (!mxData.get())
    {
        return NULL_STR;
    }

    return mxData->GetString();
}

const NFGUID& NFCProperty::GetObject() const
{
    if (!mxData.get())
    {
        return NULL_OBJECT;
    }

    return mxData->GetObject();
}

void NFCProperty::RegisterCallback(const PROPERTY_EVENT_FUNCTOR_PTR& cb)
{
    mtPropertyCallback.push_back(cb);
}

int NFCProperty::OnEventHandler(const NFIDataList::TData& oldVar, const NFIDataList::TData& newVar)
{
    if (mtPropertyCallback.size() <= 0)
    {
        return 0;
    }

    TPROPERTYCALLBACKEX::iterator it = mtPropertyCallback.begin();
    TPROPERTYCALLBACKEX::iterator end = mtPropertyCallback.end();
    for (it; it != end; ++it)
    {
        //NFIDataList:OLDֵNEWֵ, ARG(pKernel,self)
        PROPERTY_EVENT_FUNCTOR_PTR& pFunPtr = *it;
        PROPERTY_EVENT_FUNCTOR* pFunc = pFunPtr.get();
        int nTemRet = pFunc->operator()(mSelf, msPropertyName, oldVar, newVar);
    }

    return 0;
}

bool NFCProperty::SetInt(const NFINT64 value)
{
    if (eType != TDATA_INT)
    {
        return false;
    }

    if (!mxData.get())
    {
        //ǿվΪûݣûݵľͲ
        if (0 == value)
        {
            return false;
        }

        mxData = NF_SHARE_PTR<NFIDataList::TData>(NF_NEW NFIDataList::TData(TDATA_INT));
        mxData->SetInt(0);
    }

    if (value == mxData->GetInt())
    {
        return false;
    }

    NFCDataList::TData oldValue;
    oldValue = *mxData;

    mxData->SetInt(value);

    OnEventHandler(oldValue, *mxData);

    return true;
}

bool NFCProperty::SetFloat(const double value)
{
    if (eType != TDATA_FLOAT)
    {
        return false;
    }

    if (!mxData.get())
    {
        //ǿվΪûݣûݵľͲ
        if (std::abs(value) < 0.001)
        {
            return false;
        }

        mxData = NF_SHARE_PTR<NFIDataList::TData>(NF_NEW NFIDataList::TData(TDATA_FLOAT));
        mxData->SetFloat(0.0);
    }

    if (value - mxData->GetFloat() < 0.001)
    {
        return false;
    }

    NFCDataList::TData oldValue;
    oldValue = *mxData;

    mxData->SetFloat(value);

    OnEventHandler(oldValue, *mxData);

    return true;
}

bool NFCProperty::SetString(const std::string& value)
{
    if (eType != TDATA_STRING)
    {
        return false;
    }

    if (!mxData.get())
    {
        //ǿվΪûݣûݵľͲ
        if (value.empty())
        {
            return false;
        }

        mxData = NF_SHARE_PTR<NFIDataList::TData>(NF_NEW NFIDataList::TData(TDATA_STRING));
        mxData->SetString(NULL_STR);
    }

    if (value == mxData->GetString())
    {
        return false;
    }

    NFCDataList::TData oldValue;
    oldValue = *mxData;

    mxData->SetString(value);

    OnEventHandler(oldValue, *mxData);

    return true;
}

bool NFCProperty::SetObject(const NFGUID& value)
{
    if (eType != TDATA_OBJECT)
    {
        return false;
    }

    if (!mxData.get())
    {
        //ǿվΪûݣûݵľͲ
        if (value.IsNull())
        {
            return false;
        }

        mxData = NF_SHARE_PTR<NFIDataList::TData>(NF_NEW NFIDataList::TData(TDATA_OBJECT));
        mxData->SetObject(NFGUID());

    }

    if (value == mxData->GetObject())
    {
        return false;
    }

    NFCDataList::TData oldValue;
    oldValue = *mxData;

    mxData->SetObject(value);

    OnEventHandler(oldValue , *mxData);

    return true;
}

bool NFCProperty::Changed() const
{
    return GetValue().IsNullValue();
}

const TDATA_TYPE NFCProperty::GetType() const
{
    return eType;
}

const bool NFCProperty::GeUsed() const
{
    if (mxData.get())
    {
        return true;
    }

    return false;
}

std::string NFCProperty::ToString()
{
    std::string strData;
    const TDATA_TYPE eType = GetType();
    switch (eType)
    {
        case TDATA_INT:
            strData = lexical_cast<std::string> (GetInt());
            break;
        case TDATA_FLOAT:
            strData = lexical_cast<std::string> (GetFloat());
            break;
        case TDATA_STRING:
            strData = GetString();
            break;
		case TDATA_OBJECT:
            strData = GetObject().ToString();
            break;
        default:
            strData = NULL_STR;
            break;
    }

    return strData;
}

bool NFCProperty::FromString(const std::string& strData)
{
    const TDATA_TYPE eType = GetType();
    bool bRet = false;
    switch (eType)
    {
        case TDATA_INT:
        {
            NFINT64  nValue = 0;
            bRet = NF_StrTo(strData, nValue);
            SetInt(nValue);
        }
        break;

        case TDATA_FLOAT:
        {
            double  dValue = 0;
            bRet = NF_StrTo(strData, dValue);
            SetFloat(dValue);
        }
        break;

        case TDATA_STRING:
        {
            SetString(strData);
            bRet = true;
        }
        break;
        case TDATA_OBJECT:
        {
            NFGUID xID;

            bRet = xID.FromString(strData);
            SetObject(xID);
        }
        break;
        default:
            break;
    }

    return bRet;
}

bool NFCProperty::DeSerialization()
{
    bool bRet = false;

    const TDATA_TYPE eType = GetType();
    if (eType == TDATA_STRING)
    {
        NFCDataList xDataList;
        const std::string& strData = mxData->GetString();

        xDataList.Split(strData.c_str(), ";");
        for (int i = 0; i < xDataList.GetCount(); ++i)
        {
            if (nullptr == mxEmbeddedList)
            {
                mxEmbeddedList = NF_SHARE_PTR<NFList<std::string>>(NF_NEW NFList<std::string>());
            }
            else
            {
                mxEmbeddedList->ClearAll();
            }

            if(xDataList.String(i).empty())
            {
                NFASSERT(0, strData, __FILE__, __FUNCTION__);
            }

            mxEmbeddedList->Add(xDataList.String(i));
        }

        if (nullptr != mxEmbeddedList && mxEmbeddedList->Count() > 0)
        {
            std::string strTemData;
            for (bool bListRet = mxEmbeddedList->First(strTemData); bListRet == true; bListRet = mxEmbeddedList->Next(strTemData))
            {
                NFCDataList xTemDataList;
                xTemDataList.Split(strTemData.c_str(), ",");
                if (xTemDataList.GetCount() > 0)
                {
                    if (xTemDataList.GetCount() != 2)
                    {
                        NFASSERT(0, strTemData, __FILE__, __FUNCTION__);
                    }

                    const std::string& strKey = xTemDataList.String(0);
                    const std::string& strValue = xTemDataList.String(0);

                    if (strKey.empty() || strValue.empty())
                    {
                        NFASSERT(0, strTemData, __FILE__, __FUNCTION__);
                    }

                    if (nullptr == mxEmbeddedMap)
                    {
                        mxEmbeddedMap = NF_SHARE_PTR<NFMapEx<std::string, std::string>>(NF_NEW NFMapEx<std::string, std::string>());
                    }
                    else
                    {
                        mxEmbeddedMap->ClearAll();
                    }

                    mxEmbeddedMap->AddElement(strKey, NF_SHARE_PTR<std::string>(NF_NEW std::string(strValue)))
                }
            }

            bRet = true;
        }
    }

    return bRet;
}

const NF_SHARE_PTR<NFList<std::string>> NFCProperty::GetEmbeddedList() const
{
    return this->mxEmbeddedList;
}

const NF_SHARE_PTR<NFMapEx<std::string, std::string>> NFCProperty::GetEmbeddedMap() const
{
    return this->mxEmbeddedMap;
}
<commit_msg>fixed<commit_after>// -------------------------------------------------------------------------
//    @FileName         :    NFCProperty.cpp
//    @Author           :    LvSheng.Huang
//    @Date             :    2012-03-01
//    @Module           :    NFCProperty
//
// -------------------------------------------------------------------------

#include "NFCProperty.h"
#include <complex>

NFCProperty::NFCProperty()
{
    mbPublic = false;
    mbPrivate = false;
    mbSave = false;
    mSelf = NFGUID();
    eType = TDATA_UNKNOWN;

    msPropertyName = "";
}

NFCProperty::NFCProperty(const NFGUID& self, const std::string& strPropertyName, const TDATA_TYPE varType, bool bPublic,  bool bPrivate,  bool bSave, const std::string& strRelationValue)
{

    mbPublic = bPublic;
    mbPrivate = bPrivate;
    mbSave = bSave;
    mSelf = self;

    msPropertyName = strPropertyName;
    mstrRelationValue = strRelationValue;
    eType = varType;
}

NFCProperty::~NFCProperty()
{
    for (TPROPERTYCALLBACKEX::iterator iter = mtPropertyCallback.begin(); iter != mtPropertyCallback.end(); ++iter)
    {
        iter->reset();
    }

    mtPropertyCallback.clear();
    mxData.reset();
}

void NFCProperty::SetValue(const NFIDataList::TData& TData)
{
    if (eType != TData.GetType())
    {
        return;
    }

    if (!mxData.get())
    {
        if (!TData.IsNullValue())
        {
            return;
        }

        mxData = NF_SHARE_PTR<NFIDataList::TData>(NF_NEW NFIDataList::TData(TData));
    }

    NFCDataList::TData oldValue;
    oldValue = *mxData;

    mxData->variantData = TData.variantData;

    NFCDataList::TData newValue;
    newValue = *mxData;

    OnEventHandler(oldValue , newValue);
}

void NFCProperty::SetValue(const NFIProperty* pProperty)
{
    SetValue(pProperty->GetValue());
}

const NFIDataList::TData& NFCProperty::GetValue() const
{
    if (mxData.get())
    {
        return *mxData;
    }

    return NULL_TDATA;
}

const std::string&  NFCProperty::GetKey() const
{
    return msPropertyName;
}

const bool NFCProperty::GetSave() const
{
    return mbSave;
}

const bool NFCProperty::GetPublic() const
{
    return mbPublic;
}

const bool NFCProperty::GetPrivate() const
{
    return mbPrivate;
}

const std::string& NFCProperty::GetRelationValue() const
{
    return mstrRelationValue;
}

void NFCProperty::SetSave(bool bSave)
{
    mbSave = bSave;
}

void NFCProperty::SetPublic(bool bPublic)
{
    mbPublic = bPublic;
}

void NFCProperty::SetPrivate(bool bPrivate)
{
    mbPrivate = bPrivate;
}

void NFCProperty::SetRelationValue(const std::string& strRelationValue)
{
    mstrRelationValue = strRelationValue;
}

NFINT64 NFCProperty::GetInt() const
{
    if (!mxData.get())
    {
        return 0;
    }

    return mxData->GetInt();
}

double NFCProperty::GetFloat() const
{
    if (!mxData.get())
    {
        return 0.0;
    }

    return mxData->GetFloat();
}

const std::string& NFCProperty::GetString() const
{
    if (!mxData.get())
    {
        return NULL_STR;
    }

    return mxData->GetString();
}

const NFGUID& NFCProperty::GetObject() const
{
    if (!mxData.get())
    {
        return NULL_OBJECT;
    }

    return mxData->GetObject();
}

void NFCProperty::RegisterCallback(const PROPERTY_EVENT_FUNCTOR_PTR& cb)
{
    mtPropertyCallback.push_back(cb);
}

int NFCProperty::OnEventHandler(const NFIDataList::TData& oldVar, const NFIDataList::TData& newVar)
{
    if (mtPropertyCallback.size() <= 0)
    {
        return 0;
    }

    TPROPERTYCALLBACKEX::iterator it = mtPropertyCallback.begin();
    TPROPERTYCALLBACKEX::iterator end = mtPropertyCallback.end();
    for (it; it != end; ++it)
    {
        //NFIDataList:OLDֵNEWֵ, ARG(pKernel,self)
        PROPERTY_EVENT_FUNCTOR_PTR& pFunPtr = *it;
        PROPERTY_EVENT_FUNCTOR* pFunc = pFunPtr.get();
        int nTemRet = pFunc->operator()(mSelf, msPropertyName, oldVar, newVar);
    }

    return 0;
}

bool NFCProperty::SetInt(const NFINT64 value)
{
    if (eType != TDATA_INT)
    {
        return false;
    }

    if (!mxData.get())
    {
        //ǿվΪûݣûݵľͲ
        if (0 == value)
        {
            return false;
        }

        mxData = NF_SHARE_PTR<NFIDataList::TData>(NF_NEW NFIDataList::TData(TDATA_INT));
        mxData->SetInt(0);
    }

    if (value == mxData->GetInt())
    {
        return false;
    }

    NFCDataList::TData oldValue;
    oldValue = *mxData;

    mxData->SetInt(value);

    OnEventHandler(oldValue, *mxData);

    return true;
}

bool NFCProperty::SetFloat(const double value)
{
    if (eType != TDATA_FLOAT)
    {
        return false;
    }

    if (!mxData.get())
    {
        //ǿվΪûݣûݵľͲ
        if (std::abs(value) < 0.001)
        {
            return false;
        }

        mxData = NF_SHARE_PTR<NFIDataList::TData>(NF_NEW NFIDataList::TData(TDATA_FLOAT));
        mxData->SetFloat(0.0);
    }

    if (value - mxData->GetFloat() < 0.001)
    {
        return false;
    }

    NFCDataList::TData oldValue;
    oldValue = *mxData;

    mxData->SetFloat(value);

    OnEventHandler(oldValue, *mxData);

    return true;
}

bool NFCProperty::SetString(const std::string& value)
{
    if (eType != TDATA_STRING)
    {
        return false;
    }

    if (!mxData.get())
    {
        //ǿվΪûݣûݵľͲ
        if (value.empty())
        {
            return false;
        }

        mxData = NF_SHARE_PTR<NFIDataList::TData>(NF_NEW NFIDataList::TData(TDATA_STRING));
        mxData->SetString(NULL_STR);
    }

    if (value == mxData->GetString())
    {
        return false;
    }

    NFCDataList::TData oldValue;
    oldValue = *mxData;

    mxData->SetString(value);

    OnEventHandler(oldValue, *mxData);

    return true;
}

bool NFCProperty::SetObject(const NFGUID& value)
{
    if (eType != TDATA_OBJECT)
    {
        return false;
    }

    if (!mxData.get())
    {
        //ǿվΪûݣûݵľͲ
        if (value.IsNull())
        {
            return false;
        }

        mxData = NF_SHARE_PTR<NFIDataList::TData>(NF_NEW NFIDataList::TData(TDATA_OBJECT));
        mxData->SetObject(NFGUID());

    }

    if (value == mxData->GetObject())
    {
        return false;
    }

    NFCDataList::TData oldValue;
    oldValue = *mxData;

    mxData->SetObject(value);

    OnEventHandler(oldValue , *mxData);

    return true;
}

bool NFCProperty::Changed() const
{
    return GetValue().IsNullValue();
}

const TDATA_TYPE NFCProperty::GetType() const
{
    return eType;
}

const bool NFCProperty::GeUsed() const
{
    if (mxData.get())
    {
        return true;
    }

    return false;
}

std::string NFCProperty::ToString()
{
    std::string strData;
    const TDATA_TYPE eType = GetType();
    switch (eType)
    {
        case TDATA_INT:
            strData = lexical_cast<std::string> (GetInt());
            break;
        case TDATA_FLOAT:
            strData = lexical_cast<std::string> (GetFloat());
            break;
        case TDATA_STRING:
            strData = GetString();
            break;
		case TDATA_OBJECT:
            strData = GetObject().ToString();
            break;
        default:
            strData = NULL_STR;
            break;
    }

    return strData;
}

bool NFCProperty::FromString(const std::string& strData)
{
    const TDATA_TYPE eType = GetType();
    bool bRet = false;
    switch (eType)
    {
        case TDATA_INT:
        {
            NFINT64  nValue = 0;
            bRet = NF_StrTo(strData, nValue);
            SetInt(nValue);
        }
        break;

        case TDATA_FLOAT:
        {
            double  dValue = 0;
            bRet = NF_StrTo(strData, dValue);
            SetFloat(dValue);
        }
        break;

        case TDATA_STRING:
        {
            SetString(strData);
            bRet = true;
        }
        break;
        case TDATA_OBJECT:
        {
            NFGUID xID;

            bRet = xID.FromString(strData);
            SetObject(xID);
        }
        break;
        default:
            break;
    }

    return bRet;
}

bool NFCProperty::DeSerialization()
{
    bool bRet = false;

    const TDATA_TYPE eType = GetType();
    if (eType == TDATA_STRING)
    {
        NFCDataList xDataList;
        const std::string& strData = mxData->GetString();

        xDataList.Split(strData.c_str(), ";");
        for (int i = 0; i < xDataList.GetCount(); ++i)
        {
            if (nullptr == mxEmbeddedList)
            {
                mxEmbeddedList = NF_SHARE_PTR<NFList<std::string>>(NF_NEW NFList<std::string>());
            }
            else
            {
                mxEmbeddedList->ClearAll();
            }

            if(xDataList.String(i).empty())
            {
                NFASSERT(0, strData, __FILE__, __FUNCTION__);
            }

            mxEmbeddedList->Add(xDataList.String(i));
        }

        if (nullptr != mxEmbeddedList && mxEmbeddedList->Count() > 0)
        {
            std::string strTemData;
            for (bool bListRet = mxEmbeddedList->First(strTemData); bListRet == true; bListRet = mxEmbeddedList->Next(strTemData))
            {
                NFCDataList xTemDataList;
                xTemDataList.Split(strTemData.c_str(), ",");
                if (xTemDataList.GetCount() > 0)
                {
                    if (xTemDataList.GetCount() != 2)
                    {
                        NFASSERT(0, strTemData, __FILE__, __FUNCTION__);
                    }

                    const std::string& strKey = xTemDataList.String(0);
                    const std::string& strValue = xTemDataList.String(0);

                    if (strKey.empty() || strValue.empty())
                    {
                        NFASSERT(0, strTemData, __FILE__, __FUNCTION__);
                    }

                    if (nullptr == mxEmbeddedMap)
                    {
                        mxEmbeddedMap = NF_SHARE_PTR<NFMapEx<std::string, std::string>>(NF_NEW NFMapEx<std::string, std::string>());
                    }
                    else
                    {
                        mxEmbeddedMap->ClearAll();
                    }

                    mxEmbeddedMap->AddElement(strKey, NF_SHARE_PTR<std::string>(NF_NEW std::string(strValue)));
                }
            }

            bRet = true;
        }
    }

    return bRet;
}

const NF_SHARE_PTR<NFList<std::string>> NFCProperty::GetEmbeddedList() const
{
    return this->mxEmbeddedList;
}

const NF_SHARE_PTR<NFMapEx<std::string, std::string>> NFCProperty::GetEmbeddedMap() const
{
    return this->mxEmbeddedMap;
}
<|endoftext|>


<commit_before><commit_msg>fix timer<commit_after><|endoftext|>


<commit_before>#include "response.h"
#include <regex>
#include <iostream>
#include <algorithm>

using namespace std;
const char* STATUSLINE_PATTERN1 = "HTTP/([\\d\\.]+)\\s([\\d]+)\\s([\\w\\.-]+)\\r\\n";
const char* STATUSLINE_PATTERN = "(.*?)\\s(.*?)\\s(.*?)\\r\\n";
const char* HEADER_PATTERN = "(.*?):\\s(.*?)\\r\\n";

bool ci_compare(char lhs, char rhs)
{
    return ::tolower(lhs) == ::tolower(rhs);
}

HttpResponse::HttpResponse() :
    version_(""),
    phrase_(""),
    status_code_(0),
    headers_(),
    body_("")
{

}

HttpResponse::~HttpResponse()
{

}

bool HttpResponse::ParseStatus(const std::string & status)
{
    regex rex(STATUSLINE_PATTERN);
    smatch match;
    if (regex_match(status, match, rex))
    {
        version_ = match.str(1);
        status_code_ = stoi(match.str(2));
        phrase_ = match.str(3);
        return true;
    }
    cout << "could not parse status: " << status << endl;
    return false;
}

bool HttpResponse::ParseHeader(const std::string & header)
{
    regex rex(HEADER_PATTERN);
    smatch match;
    if (regex_match(header, match, rex))
    {
        headers_[match.str(1)] = match.str(2);
        return true;
    }
    cout << "[Cound not parse header] " << header << endl;

    return false;
}

std::string HttpResponse::Header(const string &key)
{
    auto it = headers_.find(key);
    if (it == headers_.end())
    {
        for(auto it : headers_)
        {
            if (it.first.size() == key.size() &&
                std::equal(it.first.begin(), it.first.end(), key.begin(), ci_compare))
            {
                return it.second;
            }

        }
        return "";
    }
    return it->second;
}

void HttpResponse::SetBody(char * buffer, unsigned int length, bool append)
{
    if (!append)
    {
        body_.assign(buffer, length);
    }
    else
    {
        body_.append(buffer, length);
    }
}

const char* HttpResponse::GetBody()
{
    return body_.data();
}<commit_msg>removed dead code<commit_after>#include "response.h"
#include <regex>
#include <iostream>
#include <algorithm>

using namespace std;
const char* STATUSLINE_PATTERN = "(.*?)\\s(.*?)\\s(.*?)\\r\\n";
const char* HEADER_PATTERN = "(.*?):\\s(.*?)\\r\\n";

bool ci_compare(char lhs, char rhs)
{
    return ::tolower(lhs) == ::tolower(rhs);
}

HttpResponse::HttpResponse() :
    version_(""),
    phrase_(""),
    status_code_(0),
    headers_(),
    body_("")
{

}

HttpResponse::~HttpResponse()
{

}

bool HttpResponse::ParseStatus(const std::string & status)
{
    regex rex(STATUSLINE_PATTERN);
    smatch match;
    if (regex_match(status, match, rex))
    {
        version_ = match.str(1);
        status_code_ = stoi(match.str(2));
        phrase_ = match.str(3);
        return true;
    }
    cout << "could not parse status: " << status << endl;
    return false;
}

bool HttpResponse::ParseHeader(const std::string & header)
{
    regex rex(HEADER_PATTERN);
    smatch match;
    if (regex_match(header, match, rex))
    {
        headers_[match.str(1)] = match.str(2);
        return true;
    }
    cout << "[Cound not parse header] " << header << endl;

    return false;
}

std::string HttpResponse::Header(const string &key)
{
    auto it = headers_.find(key);
    if (it == headers_.end())
    {
        for(auto it : headers_)
        {
            if (it.first.size() == key.size() &&
                std::equal(it.first.begin(), it.first.end(), key.begin(), ci_compare))
            {
                return it.second;
            }

        }
        return "";
    }
    return it->second;
}

void HttpResponse::SetBody(char * buffer, unsigned int length, bool append)
{
    if (!append)
    {
        body_.assign(buffer, length);
    }
    else
    {
        body_.append(buffer, length);
    }
}

const char* HttpResponse::GetBody()
{
    return body_.data();
}<|endoftext|>


<commit_before>/*
** Copyright 2014-2017 Robert Fratto. See the LICENSE.txt file at the top-level
** directory of this distribution.
**
** Licensed under the MIT license <http://opensource.org/licenses/MIT>. This file
** may not be copied, modified, or distributed except according to those terms.
*/

#include <gtest/gtest.h>

#include <sstream>
#include <stdexcept>

#include "lexeme.h"
#include "tokens.h"
#include "lexer.h"

using namespace orange::parse;

#define TEST_TOKEN(NAME, INPUT, EXPECTED_TOKEN) \
{\
			std::stringstream ss(INPUT); \
			Lexer lex(ss); \
			EXPECT_EQ(lex.next().token, EXPECTED_TOKEN); \
}

#define TEST_VALUE(NAME, INPUT, EXPECTED_VALUE) \
{\
			std::stringstream ss(INPUT); \
			Lexer lex(ss); \
			EXPECT_EQ(lex.next().value, EXPECTED_VALUE); \
}

#define TEST_INVALID(NAME, INPUT) \
{\
			std::stringstream ss(INPUT); \
			Lexer lex(ss); \
			EXPECT_THROW(lex.next(), std::runtime_error); \
}

//
//   NUMBERS TESTS
//

TEST(Lexer, TestTypes) {
	TEST_TOKEN(BinaryNoSuffix, "0b01",                     Token::UINT_VAL);
	TEST_TOKEN(OctalNoSuffix,  "0o01234567",               Token::UINT_VAL);
	TEST_TOKEN(HexNoSuffix,    "0x0123456789abcdefABCDEF", Token::UINT_VAL);
	TEST_TOKEN(DecNoSuffix,    "1234567890",               Token::INT_VAL);
	TEST_TOKEN(Double,         "1234.567890",              Token::DOUBLE_VAL);
	TEST_TOKEN(Float,          "1234.567890f",             Token::FLOAT_VAL);
	TEST_TOKEN(DoubleLeadZero, "1234.0567890",             Token::DOUBLE_VAL);
	TEST_TOKEN(FloatLeadZero,  "1234.0567890f",            Token::FLOAT_VAL);
}

TEST(Lexer, TestSuffixedTypes) {
	TEST_TOKEN(BinarySuffixU, "0b11u", Token::UINT_VAL);
	TEST_TOKEN(OctalSuffixU,  "0o32u", Token::UINT_VAL);
	TEST_TOKEN(HexSuffixU,    "0xFAu", Token::UINT_VAL);
	TEST_TOKEN(DecSuffixU,    "12u",   Token::UINT_VAL);

	TEST_TOKEN(BinarySuffixU8, "0b11u8", Token::UINT8_VAL);
	TEST_TOKEN(OctalSuffixU8,  "0o32u8", Token::UINT8_VAL);
	TEST_TOKEN(HexSuffixU8,    "0xFAu8", Token::UINT8_VAL);
	TEST_TOKEN(DecSuffixU8,    "12u8",   Token::UINT8_VAL);

	TEST_TOKEN(BinarySuffixU16, "0b11u16", Token::UINT16_VAL);
	TEST_TOKEN(OctalSuffixU16,  "0o32u16", Token::UINT16_VAL);
	TEST_TOKEN(HexSuffixU16,    "0xFAu16", Token::UINT16_VAL);
	TEST_TOKEN(DecSuffixU16,    "12u16",   Token::UINT16_VAL);

	TEST_TOKEN(BinarySuffixU32, "0b11u32", Token::UINT32_VAL);
	TEST_TOKEN(OctalSuffixU32,  "0o32u32", Token::UINT32_VAL);
	TEST_TOKEN(HexSuffixU32,    "0xFAu32", Token::UINT32_VAL);
	TEST_TOKEN(DecSuffixU32,    "12u32",   Token::UINT32_VAL);

	TEST_TOKEN(BinarySuffixU64, "0b11u64", Token::UINT64_VAL);
	TEST_TOKEN(OctalSuffixU64,  "0o32u64", Token::UINT64_VAL);
	TEST_TOKEN(HexSuffixU64,    "0xFAu64", Token::UINT64_VAL);
	TEST_TOKEN(DecSuffixU64,    "12u64",   Token::UINT64_VAL);

	TEST_TOKEN(BinarySuffixI, "0b11i", Token::UINT_VAL);
	TEST_TOKEN(OctalSuffixI,  "0o32i", Token::UINT_VAL);
	TEST_TOKEN(HexSuffixI,    "0xFAi", Token::UINT_VAL);
	TEST_TOKEN(DecSuffixI,    "12i",   Token::UINT_VAL);

	TEST_TOKEN(BinarySuffixI8, "0b11i8", Token::UINT8_VAL);
	TEST_TOKEN(OctalSuffixI8,  "0o32i8", Token::UINT8_VAL);
	TEST_TOKEN(HexSuffixI8,    "0xFAi8", Token::UINT8_VAL);
	TEST_TOKEN(DecSuffixI8,    "12i8",   Token::UINT8_VAL);

	TEST_TOKEN(BinarySuffixI16, "0b11i16", Token::UINT16_VAL);
	TEST_TOKEN(OctalSuffixI16,  "0o32i16", Token::UINT16_VAL);
	TEST_TOKEN(HexSuffixI16,    "0xFAi16", Token::UINT16_VAL);
	TEST_TOKEN(DecSuffixI16,    "12i16",   Token::UINT16_VAL);

	TEST_TOKEN(BinarySuffixI32, "0b11i32", Token::UINT32_VAL);
	TEST_TOKEN(OctalSuffixI32,  "0o32i32", Token::UINT32_VAL);
	TEST_TOKEN(HexSuffixI32,    "0xFAi32", Token::UINT32_VAL);
	TEST_TOKEN(DecSuffixI32,    "12i32",   Token::UINT32_VAL);

	TEST_TOKEN(BinarySuffixI64, "0b11i64", Token::UINT64_VAL);
	TEST_TOKEN(OctalSuffixI64,  "0o32i64", Token::UINT64_VAL);
	TEST_TOKEN(HexSuffixI64,    "0xFAi64", Token::UINT64_VAL);
	TEST_TOKEN(DecSuffixI64,    "12i64",   Token::UINT64_VAL);
}

TEST(Lexer, TestSeparators) {
	TEST_TOKEN(BinarySep, "0b0000_1111_1010_2_1__2",  Token::UINT_VAL);
	TEST_TOKEN(OctalSep,  "0o12_345_76__3",           Token::UINT_VAL);
	TEST_TOKEN(HexSep,    "0xAAAA_BBBB_C_D_123",      Token::UINT_VAL);
	TEST_TOKEN(DecSep,    "123_456_78_9",             Token::INT_VAL);
	TEST_TOKEN(DoubleSep, "12_34.5_6_78__90",         Token::DOUBLE_VAL);
	TEST_TOKEN(FloatSetp, "12_34.5_67__89_0_f",       Token::FLOAT_VAL);
}

TEST(Lexer, TestValues) {
	TEST_VALUE(BinaryVal, "0b1111",   "15");
	TEST_VALUE(OctalVal,  "0o75",     "61");
	TEST_VALUE(HexVal,    "0xF1",     "241");
	TEST_VALUE(DecVal,    "9501",     "9501");
	TEST_VALUE(DoubleVal, "59.210",   "59.210");
	TEST_VALUE(FloatVal,  "989.210f", "989.210");
}

TEST(Lexer, LeadingZeroesValues) {
	TEST_VALUE(BinaryValLeadZero, "0b01111",  "15");
	TEST_VALUE(OctalValLeadZero,  "0o075",    "61");
	TEST_VALUE(HexValLeadZero,    "0x0F1",    "241");
}

TEST(Lexer, ValuesWithSuffixes) {
	TEST_VALUE(BinarySuffixU, "0b11u", "3");
	TEST_VALUE(OctalSuffixU,  "0o32u", "26");
	TEST_VALUE(HexSuffixU,    "0xFAu", "250");
	TEST_VALUE(DecSuffixU,    "12u",   "12");

	TEST_VALUE(BinarySuffixU8, "0b11u8", "3");
	TEST_VALUE(OctalSuffixU8,  "0o32u8", "26");
	TEST_VALUE(HexSuffixU8,    "0xFAu8", "250");
	TEST_VALUE(DecSuffixU8,    "12u8",   "12");

	TEST_VALUE(BinarySuffixU16, "0b11u16", "3");
	TEST_VALUE(OctalSuffixU16,  "0o32u16", "26");
	TEST_VALUE(HexSuffixU16,    "0xFAu16", "250");
	TEST_VALUE(DecSuffixU16,    "12u16",   "12");

	TEST_VALUE(BinarySuffixU32, "0b11u32", "3");
	TEST_VALUE(OctalSuffixU32,  "0o32u32", "26");
	TEST_VALUE(HexSuffixU32,    "0xFAu32", "250");
	TEST_VALUE(DecSuffixU32,    "12u32",   "12");

	TEST_VALUE(BinarySuffixU64, "0b11u64", "3");
	TEST_VALUE(OctalSuffixU64,  "0o32u64", "26");
	TEST_VALUE(HexSuffixU64,    "0xFAu64", "250");
	TEST_VALUE(DecSuffixU64,    "12u64",   "12");

	TEST_VALUE(BinarySuffixI, "0b11i", "3");
	TEST_VALUE(OctalSuffixI,  "0o32i", "26");
	TEST_VALUE(HexSuffixI,    "0xFAi", "250");
	TEST_VALUE(DecSuffixI,    "12i",   "12");

	TEST_VALUE(BinarySuffixI8, "0b11i8", "3");
	TEST_VALUE(OctalSuffixI8,  "0o32i8", "26");
	TEST_VALUE(HexSuffixI8,    "0xFAi8", "250");
	TEST_VALUE(DecSuffixI8,    "12i8",   "12");

	TEST_VALUE(BinarySuffixI16, "0b11i16", "3");
	TEST_VALUE(OctalSuffixI16,  "0o32i16", "26");
	TEST_VALUE(HexSuffixI16,    "0xFAi16", "250");
	TEST_VALUE(DecSuffixI16,    "12i16",   "12");

	TEST_VALUE(BinarySuffixI32, "0b11i32", "3");
	TEST_VALUE(OctalSuffixI32,  "0o32i32", "26");
	TEST_VALUE(HexSuffixI32,    "0xFAi32", "250");
	TEST_VALUE(DecSuffixI32,    "12i32",   "12");

	TEST_VALUE(BinarySuffixI64, "0b11i64", "3");
	TEST_VALUE(OctalSuffixI64,  "0o32i64", "26");
	TEST_VALUE(HexSuffixI64,    "0xFAi64", "250");
	TEST_VALUE(DecSuffixI64,    "12i64",   "12");
}

TEST(Lexer, InvalidNumbers) {
	TEST_INVALID(LeadingZeroLetter, "0d51");
	TEST_INVALID(LeadingZeroNumber, "052");
	TEST_INVALID(InvalidSuffix, "32z");
}

<commit_msg>Refactor test_lexer.cc<commit_after>/*
** Copyright 2014-2017 Robert Fratto. See the LICENSE.txt file at the top-level
** directory of this distribution.
**
** Licensed under the MIT license <http://opensource.org/licenses/MIT>. This file
** may not be copied, modified, or distributed except according to those terms.
*/

#include <gtest/gtest.h>

#include <sstream>
#include <stdexcept>

#include "lexeme.h"
#include "tokens.h"
#include "lexer.h"

using namespace orange::parse;

#define TEST_TOKEN(INPUT, EXPECTED_TOKEN) \
{\
			std::stringstream ss(INPUT); \
			Lexer lex(ss); \
			EXPECT_EQ(lex.next().token, EXPECTED_TOKEN); \
}

#define TEST_VALUE(INPUT, EXPECTED_VALUE) \
{\
			std::stringstream ss(INPUT); \
			Lexer lex(ss); \
			EXPECT_EQ(lex.next().value, EXPECTED_VALUE); \
}

#define TEST_INVALID(INPUT) \
{\
			std::stringstream ss(INPUT); \
			Lexer lex(ss); \
			EXPECT_THROW(lex.next(), std::runtime_error); \
}

//
//   NUMBERS TESTS
//

TEST(Lexer, TestTypes) {
    std::map<std::string, Token> testTable = {
        {"0b01", Token::UINT_VAL},
		{"0o01234567", Token::UINT_VAL},
        {"0x0123456789abcdefABCDEF", Token::UINT_VAL},
        {"1234567890", Token::INT_VAL},
        {"1234.567890", Token::DOUBLE_VAL},
        {"1234.567890f", Token::FLOAT_VAL},
        {"1234.0567890", Token::DOUBLE_VAL},
        {"1234.0567890f", Token::FLOAT_VAL},
    };

	for (auto row : testTable) {
		TEST_TOKEN(row.first, row.second);
	}
}

TEST(Lexer, TestSuffixedTypes) {
	std::map<std::string, Token> testTable = {
        {"0b11u", Token::UINT_VAL},
        {"0o32u", Token::UINT_VAL},
        {"0xFAu", Token::UINT_VAL},
        {"12u", Token::UINT_VAL},
        {"0b11u8", Token::UINT8_VAL},
        {"0o32u8", Token::UINT8_VAL},
        {"0xFAu8", Token::UINT8_VAL},
        {"12u8",   Token::UINT8_VAL},
        {"0b11u16", Token::UINT16_VAL},
        {"0o32u16", Token::UINT16_VAL},
        {"0xFAu16", Token::UINT16_VAL},
        {"12u16",   Token::UINT16_VAL},
        {"0b11u32", Token::UINT32_VAL},
        {"0o32u32", Token::UINT32_VAL},
        {"0xFAu32", Token::UINT32_VAL},
        {"12u32",   Token::UINT32_VAL},
        {"0b11u64", Token::UINT64_VAL},
        {"0o32u64", Token::UINT64_VAL},
        {"0xFAu64", Token::UINT64_VAL},
        {"12u64",   Token::UINT64_VAL},
        {"0b11i", Token::UINT_VAL},
        {"0o32i", Token::UINT_VAL},
        {"0xFAi", Token::UINT_VAL},
        {"12i",   Token::UINT_VAL},
        {"0b11i8", Token::UINT8_VAL},
        {"0o32i8", Token::UINT8_VAL},
        {"0xFAi8", Token::UINT8_VAL},
        {"12i8",   Token::UINT8_VAL},
        {"0b11i16", Token::UINT16_VAL},
        {"0o32i16", Token::UINT16_VAL},
        {"0xFAi16", Token::UINT16_VAL},
        {"12i16",   Token::UINT16_VAL},
        {"0b11i32", Token::UINT32_VAL},
        {"0o32i32", Token::UINT32_VAL},
        {"0xFAi32", Token::UINT32_VAL},
        {"12i32",   Token::UINT32_VAL},
        {"0b11i64", Token::UINT64_VAL},
        {"0o32i64", Token::UINT64_VAL},
        {"0xFAi64", Token::UINT64_VAL},
        {"12i64",   Token::UINT64_VAL},
	};

 	for (auto row : testTable) {
		TEST_TOKEN(row.first, row.second);
	}
}

TEST(Lexer, TestSeparators) {
    std::map<std::string, Token> testTable = {
        {"0b0000_1111_1010_2_1__2", Token::UINT_VAL},
        {"0o12_345_76__3", Token::UINT_VAL},
        {"0xAAAA_BBBB_C_D_123", Token::UINT_VAL},
        {"123_456_78_9", Token::INT_VAL},
        {"12_34.5_6_78__90", Token::DOUBLE_VAL},
        {"12_34.5_67__89_0_f", Token::FLOAT_VAL},
	};

	for (auto row : testTable) {
		TEST_TOKEN(row.first, row.second);
	}
}

TEST(Lexer, TestValues) {
    std::map<std::string, std::string> testTable = {
        {"0b1111",   "15"},
        {"0o75",     "61"},
        {"0xF1",     "241"},
        {"9501",     "9501"},
        {"59.210",   "59.210"},
        {"989.210f", "989.210"},
	};

    for (auto row : testTable) {
		TEST_VALUE(row.first, row.second);
	}
}

TEST(Lexer, LeadingZeroesValues) {
    std::map<std::string, std::string> testTable = {
        {"0b01111",  "15"},
        {"0o075",    "61"},
        {"0x0F1",    "241"},
	};

	for (auto row : testTable) {
		TEST_VALUE(row.first, row.second);
	}
}

TEST(Lexer, ValuesWithSuffixes) {
    std::map<std::string, std::string> testTable = {
			{"0b11u", "3"},
			{"0o32u", "26"},
			{"0xFAu", "250"},
			{"12u",   "12"},
			{"0b11u8", "3"},
			{"0o32u8", "26"},
			{"0xFAu8", "250"},
			{"12u8",   "12"},
			{"0b11u16", "3"},
			{"0o32u16", "26"},
			{"0xFAu16", "250"},
			{"12u16",   "12"},
			{"0b11u32", "3"},
			{"0o32u32", "26"},
			{"0xFAu32", "250"},
			{"12u32",   "12"},
			{"0b11u64", "3"},
			{"0o32u64", "26"},
			{"0xFAu64", "250"},
			{"12u64",   "12"},
			{"0b11i", "3"},
			{"0o32i", "26"},
			{"0xFAi", "250"},
			{"12i",   "12"},
			{"0b11i8", "3"},
			{"0o32i8", "26"},
			{"0xFAi8", "250"},
			{"12i8",   "12"},
			{"0b11i16", "3"},
			{"0o32i16", "26"},
			{"0xFAi16", "250"},
			{"12i16",   "12"},
			{"0b11i32", "3"},
			{"0o32i32", "26"},
			{"0xFAi32", "250"},
			{"12i32",   "12"},
			{"0b11i64", "3"},
			{"0o32i64", "26"},
			{"0xFAi64", "250"},
			{"12i64",   "12"},
	};

	for (auto row : testTable) {
		TEST_VALUE(row.first, row.second);
	}
}

TEST(Lexer, InvalidNumbers) {
    std::vector<std::string> testTable = {
        "0d51",
        "052",
        "32z",
	};

	for (auto row : testTable) {
		TEST_INVALID(row);
	}
}

<|endoftext|>


<commit_before>// -*- C++ -*-
//===----------------------------------------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

int main()
{
}

<commit_msg>Test commit: Reverting whitespace changes<commit_after>// -*- C++ -*-
//===----------------------------------------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

int main()
{
}
<|endoftext|>


<commit_before>#include <gtest/gtest.h>
#include <ros/ros.h>
#include <actionlib/client/simple_action_client.h>
#include <actionlib/client/terminal_state.h>
#include <move_base_msgs/MoveBaseAction.h>
#include <move_basic/queued_action_server.h>
#include <queue>
#include <memory>
#include <mutex>
#include <condition_variable>

class GoalQueueSuite : public ::testing::Test {
protected:
	virtual void SetUp() {
		resetFlags();
		ros::NodeHandle actionNh("");
		qserv.reset(new actionlib::QueuedActionServer<move_base_msgs::MoveBaseAction> (actionNh, "queue_server", boost::bind(&GoalQueueSuite::executeCallback, this, _1)));
		cli.reset(new actionlib::SimpleActionClient<move_base_msgs::MoveBaseAction> ("queue_server", true)); // true -> don't need ros::spin()

		qserv->start();
	}

	virtual void TearDown() {
		// Kill the executeCallback if it is running
		// New Scope so that lock_guard destructs and unlocks
		{
			std::lock_guard<std::mutex> lk1(execute_lock);
			finish_executing = true;
			execute_cv.notify_one(); // Releases one waiting thread
		}
		qserv->shutdown();
	}

	void executeCallback(const move_base_msgs::MoveBaseGoalConstPtr &msg) {
		resetFlags();
		got_goal = true;
		received_goal = msg;
		while (true) {
			goal_preempted = qserv->isPreemptRequested() ? true : false;
			next_goal_available = qserv->isNewGoalAvailable() ? true : false;

			// Test fixture can continue
			execution = true;
			sleep_cv.notify_one();
			// Wait until signalled to end
			std::unique_lock<std::mutex> lk(execute_lock);
			execute_cv.wait(lk,
				//lambda function to wait on our bool variables
				[this](){return finish_executing || resume_executing;} // blocks only if lambda returns false
			);
			execution = false;
			// We were requested to stop, so we stop
			if (finish_executing) {
				break;
			}
		}

		// Signal that we are done here
		std::lock_guard<std::mutex> lk(execute_done_lock);
		execute_done = true;
		execute_done_cv.notify_all();
	}

	// Helper function to signal the executeCallback to end
	void finishExecuting() {
		// New Scope so that lock_guard destructs and unlocks
		{
			std::lock_guard<std::mutex> lk1(execute_lock);
			finish_executing = true;
			execute_cv.notify_one(); //unlocks lambda waiting function in ExecuteCallback
		}

		// Wait for execute callback to actually finish
		std::unique_lock<std::mutex> lk2(execute_done_lock);
		execute_done_cv.wait(lk2, [this]() {return execute_done;}); // at the end of ExecuteCallback
	}

	// Helper function to signal the executeCallback to resume
	// This is useful for seeing if the callback code sees a preempt
	void resumeExecuting() {
		std::lock_guard<std::mutex> lk(execute_lock);
		resume_executing = true;
		execute_cv.notify_one();
	}

	// Helper function to wait to for flags to update in ExecuteCallback
	void sleepExecuting() {
		std::unique_lock<std::mutex> slk(sleep_lock);
		sleep_cv.wait(slk,
				[this](){return execution;}
			);
	}

	void updateExecuting() {
		std::unique_lock<std::mutex> ulk(update_lock);
		sleep_cv.wait(ulk,
				[this](){return !execution;}
			);
	}

	void resetFlags() {
		got_goal = false;
		goal_preempted = false;
		next_goal_available = false;
		received_goal = nullptr;

		// Signal flags
		execution = false;
		finish_executing = false;
		resume_executing = false;
		execute_done = false;
	}

	// Flags for assertions
	bool got_goal;
	bool goal_preempted;
	bool next_goal_available;
	move_base_msgs::MoveBaseGoalConstPtr received_goal;

	// Signaling variables
	bool execution;
	bool finish_executing;
	bool resume_executing;
	bool execute_done;
	std::mutex sleep_lock;
	std::mutex update_lock;
	std::mutex execute_lock;
	std::mutex execute_done_lock;
	std::condition_variable sleep_cv;
	std::condition_variable execute_cv;
	std::condition_variable execute_done_cv;

	std::unique_ptr<actionlib::QueuedActionServer<move_base_msgs::MoveBaseAction>> qserv;
	std::unique_ptr<actionlib::SimpleActionClient<move_base_msgs::MoveBaseAction>> cli;
};

TEST_F(GoalQueueSuite, addGoalWhileExecuting) {
	move_base_msgs::MoveBaseGoal goal;

	// First goal
	goal.target_pose.pose.position.x = 3.0;
	cli->sendGoal(goal);
	ros::spinOnce();
	sleepExecuting();
	EXPECT_TRUE(got_goal);
	EXPECT_FALSE(goal_preempted);
	EXPECT_FALSE(next_goal_available);
	EXPECT_EQ(3.0, received_goal->target_pose.pose.position.x);

	// Second goal
	goal.target_pose.pose.position.x = 7.0;
	cli->sendGoal(goal);
	ros::spinOnce();

	resumeExecuting();
	updateExecuting();
	sleepExecuting();
 	EXPECT_TRUE(next_goal_available);

	// Cancel the last goal sent
	cli->cancelGoal();
	ros::Duration(1.0).sleep();
	ros::spinOnce();
	EXPECT_EQ(3.0, received_goal->target_pose.pose.position.x); // Making sure we are in the first goal thread
 	finishExecuting(); // Finish 1st goal
	ros::Duration(0.5).sleep();

	EXPECT_TRUE(goal_preempted);
 	finishExecuting(); // Finish 2nd (canceled) goal

	// New goal
	goal.target_pose.pose.position.x = 13.0;
	cli->sendGoal(goal);
	ros::spinOnce();
	sleepExecuting();
	EXPECT_TRUE(got_goal);
	EXPECT_FALSE(goal_preempted);
	EXPECT_EQ(13.0, received_goal->target_pose.pose.position.x);
	finishExecuting(); // Finish new goal

// 	- if another goal is received add it to the queue (DONE)
// 	- if the queue full, set the next goal as preempted - explicitly called! - so cancelling the next goal and adding new to the queue
// 	- start executing the new goal in queue (after the current)
}

TEST_F(GoalQueueSuite, stopAfterCancel) {
	move_base_msgs::MoveBaseGoal goal;

	// One goal -> Cancel request -> Stop
	goal.target_pose.pose.position.x = 3.0;
	cli->sendGoal(goal);
	ros::spinOnce();
	sleepExecuting();
	EXPECT_TRUE(got_goal);
	EXPECT_EQ(3.0, received_goal->target_pose.pose.position.x);

	cli->cancelGoal();
	ros::Duration(1.0).sleep();
	ros::spinOnce();
	resumeExecuting();
	updateExecuting();
	sleepExecuting();
	ros::Duration(0.5).sleep();
// 	EXPECT_TRUE(goal_preempted);
	finishExecuting();
	ros::Duration(0.5).sleep();
 	EXPECT_FALSE(qserv->isActive());

//	- if a cancel request is received for the current goal, set it as preempted (DONE)
//	- if no goal, stop (DONE)
}

TEST_F(GoalQueueSuite, continueAfterCancel) {
	move_base_msgs::MoveBaseGoal goal;

	// Two goals -> Cancel current goal -> Start executing the second
	goal.target_pose.pose.position.x = 3.0;
	cli->sendGoal(goal);
	ros::spinOnce();
	sleepExecuting();
	EXPECT_TRUE(got_goal);
	EXPECT_EQ(3.0, received_goal->target_pose.pose.position.x);

	// Cancelling the first goal - PITFALL
	cli->cancelGoal();
	ros::Duration(1.0).sleep();
	ros::spinOnce();
	resumeExecuting();
	updateExecuting();
	sleepExecuting();
	ASSERT_TRUE(goal_preempted);
	finishExecuting(); // Finish the preempted goal

	// "Second" goal
	goal.target_pose.pose.position.x = 7.0;
	cli->sendGoal(goal);
	ros::spinOnce();
	sleepExecuting();
	EXPECT_TRUE(got_goal);
	ASSERT_EQ(7.0, received_goal->target_pose.pose.position.x);
	finishExecuting(); // Finish 2nd goal

//	- if a cancel request is received for the current goal, set it as preempted (DONE)
//	- if there another goal, start executing it
}

TEST_F(GoalQueueSuite, goalCancelling) {
	move_base_msgs::MoveBaseGoal goal;
	goal.target_pose.pose.position.x = 3.0;

	// Two goals -> Cancel current goal -> Start executing the second
	cli->sendGoal(goal);
	ros::spinOnce();
	sleepExecuting();
	ASSERT_TRUE(got_goal);
	ASSERT_EQ(3.0, received_goal->target_pose.pose.position.x);

	// Second goal
	goal.target_pose.pose.position.x = 7.0;
	cli->sendGoal(goal);
	ros::spinOnce();

	resumeExecuting();
	updateExecuting();
	sleepExecuting();
	ASSERT_EQ(3.0, received_goal->target_pose.pose.position.x); // Making sure we are in the first goal thread
	EXPECT_TRUE(next_goal_available);

	// Cancelling the second goal
	cli->cancelGoal();
	ros::Duration(1.0).sleep();
	ros::spinOnce();

 	finishExecuting(); // finish 1st goal
 	ros::Duration(0.5).sleep(); // Needs to wait so the executeCallback can finish

	EXPECT_TRUE(goal_preempted); // Must be checked in the goal-thread that is cancelled
	finishExecuting(); // Finish the cancelled goal

// 	- if a cancel request on the "next_goal" received, remove it from the queue and set it as cancelled
}

// Two more TEST_F missing

int main(int argc, char **argv) {
    ros::init(argc, argv, "goal_queueing_test");
    testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}
<commit_msg>Clean version.<commit_after>#include <gtest/gtest.h>
#include <ros/ros.h>
#include <actionlib/client/simple_action_client.h>
#include <actionlib/client/terminal_state.h>
#include <move_base_msgs/MoveBaseAction.h>
#include <move_basic/queued_action_server.h>
#include <queue>
#include <memory>
#include <mutex>
#include <condition_variable>

class GoalQueueSuite : public ::testing::Test {
protected:
	virtual void SetUp() {
		resetFlags();
		ros::NodeHandle actionNh("");
		qserv.reset(new actionlib::QueuedActionServer<move_base_msgs::MoveBaseAction> (actionNh, "queue_server", boost::bind(&GoalQueueSuite::executeCallback, this, _1)));
		cli.reset(new actionlib::SimpleActionClient<move_base_msgs::MoveBaseAction> ("queue_server", true)); // true -> don't need ros::spin()

		qserv->start();
	}

	virtual void TearDown() {
		// Kill the executeCallback if it is running
		// New Scope so that lock_guard destructs and unlocks
		{
			std::lock_guard<std::mutex> lk1(execute_lock);
			finish_executing = true;
			execute_cv.notify_one(); // Releases one waiting thread
		}
		qserv->shutdown();
	}

	void executeCallback(const move_base_msgs::MoveBaseGoalConstPtr &msg) {
		resetFlags();
		got_goal = true;
		received_goal = msg;
		while (true) {
			goal_preempted = qserv->isPreemptRequested() ? true : false;
			next_goal_available = qserv->isNewGoalAvailable() ? true : false;

			// Test fixture can continue
			execution = true;
			sleep_cv.notify_one();
			// Wait until signalled to end
			std::unique_lock<std::mutex> lk(execute_lock);
			execute_cv.wait(lk,
				//lambda function to wait on our bool variables
				[this](){return finish_executing || resume_executing;} // blocks only if lambda returns false
			);
			execution = false;
			// We were requested to stop, so we stop
			if (finish_executing) {
				break;
			}
		}

		// Signal that we are done here
		std::lock_guard<std::mutex> lk(execute_done_lock);
		execute_done = true;
		execute_done_cv.notify_all();
	}

	// Helper function to signal the executeCallback to end
	void finishExecuting() {
		// New Scope so that lock_guard destructs and unlocks
		{
			std::lock_guard<std::mutex> lk1(execute_lock);
			finish_executing = true;
			execute_cv.notify_one(); //unlocks lambda waiting function in ExecuteCallback
		}

		// Wait for execute callback to actually finish
		std::unique_lock<std::mutex> lk2(execute_done_lock);
		execute_done_cv.wait(lk2, [this]() {return execute_done;}); // at the end of ExecuteCallback
	}

	// Helper function to signal the executeCallback to resume
	// This is useful for seeing if the callback code sees a preempt
	void resumeExecuting() {
		std::lock_guard<std::mutex> lk(execute_lock);
		resume_executing = true;
		execute_cv.notify_one();
	}

	// Helper function to wait to for flags to update in ExecuteCallback
	void sleepExecuting() {
		std::unique_lock<std::mutex> slk(sleep_lock);
		sleep_cv.wait(slk,
				[this](){return execution;}
			);
	}

	// Helper function to wait for execution variable to update
	void updateExecuting() {
		std::unique_lock<std::mutex> ulk(update_lock);
		sleep_cv.wait(ulk,
				[this](){return !execution;}
			);
	}

	void resetFlags() {
		got_goal = false;
		goal_preempted = false;
		next_goal_available = false;
		received_goal = nullptr;

		// Signal flags
		execution = false;
		finish_executing = false;
		resume_executing = false;
		execute_done = false;
	}

	// Flags for assertions
	bool got_goal;
	bool goal_preempted;
	bool next_goal_available;
	move_base_msgs::MoveBaseGoalConstPtr received_goal;

	// Signaling variables
	bool execution;
	bool finish_executing;
	bool resume_executing;
	bool execute_done;
	std::mutex sleep_lock;
	std::mutex update_lock;
	std::mutex execute_lock;
	std::mutex execute_done_lock;
	std::condition_variable sleep_cv;
	std::condition_variable execute_cv;
	std::condition_variable execute_done_cv;

	std::unique_ptr<actionlib::QueuedActionServer<move_base_msgs::MoveBaseAction>> qserv;
	std::unique_ptr<actionlib::SimpleActionClient<move_base_msgs::MoveBaseAction>> cli;
};

TEST_F(GoalQueueSuite, addGoalWhileExecuting) {
	move_base_msgs::MoveBaseGoal goal;

	// First goal
	goal.target_pose.pose.position.x = 3.0;
	cli->sendGoal(goal);
	ros::spinOnce();
	sleepExecuting();
	EXPECT_TRUE(got_goal);
	EXPECT_FALSE(goal_preempted);
	EXPECT_FALSE(next_goal_available);
	EXPECT_EQ(3.0, received_goal->target_pose.pose.position.x);

	// Second goal
	goal.target_pose.pose.position.x = 7.0;
	cli->sendGoal(goal);
	ros::spinOnce();

	resumeExecuting();
	updateExecuting();
	sleepExecuting();
 	EXPECT_TRUE(next_goal_available);

	// Cancel the last goal sent
	cli->cancelGoal();
	ros::Duration(1.0).sleep();
	ros::spinOnce();
	EXPECT_EQ(3.0, received_goal->target_pose.pose.position.x); // Making sure we are in the first goal thread
 	finishExecuting(); // Finish 1st goal
	ros::Duration(0.5).sleep();

	EXPECT_TRUE(goal_preempted);
 	finishExecuting(); // Finish 2nd (canceled) goal

	// New goal
	goal.target_pose.pose.position.x = 13.0;
	cli->sendGoal(goal);
	ros::spinOnce();
	sleepExecuting();
	EXPECT_TRUE(got_goal);
	EXPECT_FALSE(goal_preempted);
	EXPECT_EQ(13.0, received_goal->target_pose.pose.position.x);
	finishExecuting();
}

TEST_F(GoalQueueSuite, stopAfterCancel) {
	move_base_msgs::MoveBaseGoal goal;

	// One goal -> Cancel request -> Stop
	goal.target_pose.pose.position.x = 3.0;
	cli->sendGoal(goal);
	ros::spinOnce();
	sleepExecuting();
	EXPECT_TRUE(got_goal);
	EXPECT_EQ(3.0, received_goal->target_pose.pose.position.x);

	cli->cancelGoal();
	ros::Duration(1.0).sleep();
	ros::spinOnce();
	resumeExecuting();
	updateExecuting();
	sleepExecuting();
	ros::Duration(0.5).sleep();
// 	EXPECT_TRUE(goal_preempted); // TODO: Sometimes failling
	finishExecuting();
	ros::Duration(0.5).sleep();
 	EXPECT_FALSE(qserv->isActive());
}

TEST_F(GoalQueueSuite, continueAfterCancel) {
	move_base_msgs::MoveBaseGoal goal;

	// Two goals -> Cancel current goal -> Start executing the second
	goal.target_pose.pose.position.x = 3.0;
	cli->sendGoal(goal);
	ros::spinOnce();
	sleepExecuting();
	EXPECT_TRUE(got_goal);
	EXPECT_EQ(3.0, received_goal->target_pose.pose.position.x);

	// Cancelling the first goal - PITFALL
	cli->cancelGoal();
	ros::Duration(1.0).sleep();
	ros::spinOnce();
	resumeExecuting();
	updateExecuting();
	sleepExecuting();
	ASSERT_TRUE(goal_preempted);
	finishExecuting();

	// "Second" goal
	goal.target_pose.pose.position.x = 7.0;
	cli->sendGoal(goal);
	ros::spinOnce();
	sleepExecuting();
	EXPECT_TRUE(got_goal);
	ASSERT_EQ(7.0, received_goal->target_pose.pose.position.x);
	finishExecuting();
}

TEST_F(GoalQueueSuite, goalCancelling) {
	move_base_msgs::MoveBaseGoal goal;
	goal.target_pose.pose.position.x = 3.0;

	// Two goals -> Cancel current goal -> Start executing the second
	cli->sendGoal(goal);
	ros::spinOnce();
	sleepExecuting();
	ASSERT_TRUE(got_goal);
	ASSERT_EQ(3.0, received_goal->target_pose.pose.position.x);

	// Second goal
	goal.target_pose.pose.position.x = 7.0;
	cli->sendGoal(goal);
	ros::spinOnce();

	resumeExecuting();
	updateExecuting();
	sleepExecuting();
	ASSERT_EQ(3.0, received_goal->target_pose.pose.position.x);
	EXPECT_TRUE(next_goal_available);

	// Cancelling the second goal
	cli->cancelGoal();
	ros::Duration(1.0).sleep();
	ros::spinOnce();

 	finishExecuting(); // finish 1st goal
 	ros::Duration(0.5).sleep(); // Needs to wait so the executeCallback can finish

	EXPECT_TRUE(goal_preempted);
	finishExecuting(); // Finish the cancelled goal
}

// Two more TEST_F missing

int main(int argc, char **argv) {
    ros::init(argc, argv, "goal_queueing_test");
    testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}
<|endoftext|>