<commit_before>//----------------------------------*-C++-*----------------------------------//
/*!
 * \file   core/test/tstTransfer_Map.cc
 * \author Stuart Slattery
 * \date   Mon Oct 31 12:15:31 2011
 * \brief  Unit test for the transfer map.
 * \note   Copyright (C) 2008 Oak Ridge National Laboratory, UT-Battelle, LLC.
 */
//---------------------------------------------------------------------------//
// $Id: template_c4_test.cc,v 1.7 2008/01/02 22:50:26 9te Exp $
//---------------------------------------------------------------------------//

#include <iostream>
#include <vector>
#include <cmath>
#include <sstream>
#include <map>
#include <set>
#include <iterator>

#include "harness/DBC.hh"
#include "harness/Soft_Equivalence.hh"
#include "comm/global.hh"
#include "comm/Parallel_Unit_Test.hh"
#include "release/Release.hh"
#include "../Transfer_Map.hh"

using namespace std;
using nemesis::Parallel_Unit_Test;
using nemesis::soft_equiv;

using coupler::Transfer_Map;

int node  = 0;
int nodes = 0;

#define ITFAILS ut.failure(__LINE__);
#define UNIT_TEST(a) if (!(a)) ut.failure(__LINE__);

//---------------------------------------------------------------------------//
// TESTS
//---------------------------------------------------------------------------//

void map_test(Parallel_Unit_Test &ut)
{
    // Useful typedefs.
    typedef typename Transfer_Map::Map_Iterator    Map_Iterator;
    typedef typename Transfer_Map::Map_Pair        Map_Pair;
    typedef typename Transfer_Map::Set_Iterator    Set_Iterator;
    typedef typename Transfer_Map::Set_Pair        Set_Pair;

    // Make a map object with integer handles and ranks.
    Transfer_Map tmap;

    // Add domain pairs.
    tmap.add_domain_pair(1, 21);
    tmap.add_domain_pair(1, 32);
    tmap.add_domain_pair(1, 12);
    tmap.add_domain_pair(3, 2);
    tmap.add_domain_pair(4, 22);
    tmap.add_domain_pair(2, 54);
    tmap.add_domain_pair(3, 5);

    // Check the size of the domains.
    UNIT_TEST( tmap.domain_size(1) == 3 );
    UNIT_TEST( tmap.domain_size(2) == 1 );
    UNIT_TEST( tmap.domain_size(3) == 2 );
    UNIT_TEST( tmap.domain_size(4) == 1 );

    // Check the contents of the domains.
    Map_Pair domain_1 = tmap.domain(1);
    UNIT_TEST( std::distance(domain_1.first, domain_1.second) == 3 );
    UNIT_TEST( domain_1.first->second == 12 );
    UNIT_TEST( (domain_1.first+1)->second == 21 );
    UNIT_TEST( (domain_1.first+2)->second == 32 );

    Map_Pair domain_2 = tmap.domain(2);
    UNIT_TEST( std::distance(domain_2.first, domain_2.second) == 1 );
    UNIT_TEST( *((domain_2.first)->second) == 54 );

    Map_Pair domain_3 = tmap.domain(3);
    UNIT_TEST( std::distance(domain_3.first, domain_3.second) == 2 );
    UNIT_TEST( *((domain_3.first)->second) == 2 );
    UNIT_TEST( *((domain_3.first+1)->second) == 5 );

    Map_Pair domain_4 = tmap.domain(4);
    UNIT_TEST( std::distance(domain_4.first, domain_4.second) == 1 );
    UNIT_TEST( *((domain_4.first)->second) == 22 );

    // Add range pairs.
    tmap.add_range_pair(8, 9);
    tmap.add_range_pair(32, 1);
    tmap.add_range_pair(8, 4);
    tmap.add_range_pair(8, 34);
    tmap.add_range_pair(32, 3);

    // Check the size of the ranges.
    UNIT_TEST( tmap.range_size(8) == 3 );
    UNIT_TEST( tmap.range_size(32) == 2 );

    // Check the contents of the ranges.
    Map_Pair range_8 = tmap.range(8);
    UNIT_TEST( std::distance(range_8.first,range_8.second) == 3 );
    UNIT_TEST( *((range_8.first)->second) == 4 );
    UNIT_TEST( *((range_8.first+1)->second) == 9 );
    UNIT_TEST( *((range_8.first+2)->second) == 34 );

    Map_Pair range_32 = tmap.range(32);
    UNIT_TEST( std::distance(range_32.first,range_32.second) == 2 );
    UNIT_TEST( *((range_32.first)->second) == 1 );
    UNIT_TEST( *((range_32.first+1)->second) == 3 );

    // Check the source and target sets.
    Set_Pair sources = tmap.sources();
    UNIT_TEST( std::distance(sources.first, sources.second) == 2 );
    UNIT_TEST( *(sources.first) == 8 );
    UNIT_TEST( *(sources.first+1) == 32 );

    Set_Pair targets = tmap.targets();
    UNIT_TEST( std::distance(targets.first, targets.second) == 4 );
    UNIT_TEST( *(targets.first) == 1 );
    UNIT_TEST( *(targets.first+1) == 2 );
    UNIT_TEST( *(targets.first+2) == 3 );
    UNIT_TEST( *(targets.first+3) == 4 );

    if (ut.numFails == 0)
    {
        std::ostringstream m;
        m << "Transfer_Map test passes on " << node;
        ut.passes( m.str() );
    }
}

//---------------------------------------------------------------------------//

int main(int argc, char *argv[])
{
    Parallel_Unit_Test ut(argc, argv, coupler::release);

    node  = nemesis::node();
    nodes = nemesis::nodes();

    try
    {
        // >>> UNIT TESTS
        int gpass = 0;
        int gfail = 0;

	map_test(ut);
	gpass += ut.numPasses;
	gfail += ut.numFails;
	ut.reset();

        // add up global passes and fails
        nemesis::global_sum(gpass);
        nemesis::global_sum(gfail);
	ut.numPasses = gpass;
        ut.numFails  = gfail;
    }
    catch (std::exception &err)
    {
        std::cout << "ERROR: While testing tstTransfer_Map, "
                  << err.what()
                  << endl;
        ut.numFails++;
    }
    catch( ... )
    {
        std::cout << "ERROR: While testing tstTransfer_Map, "
                  << "An unknown exception was thrown."
                  << endl;
        ut.numFails++;
    }
    return ut.numFails;
}

//---------------------------------------------------------------------------//
//                        end of tstTransfer_Map.cc
//---------------------------------------------------------------------------//
<commit_msg>Fixed Transfer_Map unit test. Passes in parallel<commit_after>//----------------------------------*-C++-*----------------------------------//
/*!
 * \file   core/test/tstTransfer_Map.cc
 * \author Stuart Slattery
 * \date   Mon Oct 31 12:15:31 2011
 * \brief  Unit test for the transfer map.
 * \note   Copyright (C) 2008 Oak Ridge National Laboratory, UT-Battelle, LLC.
 */
//---------------------------------------------------------------------------//
// $Id: template_c4_test.cc,v 1.7 2008/01/02 22:50:26 9te Exp $
//---------------------------------------------------------------------------//

#include <iostream>
#include <vector>
#include <cmath>
#include <sstream>
#include <map>
#include <set>
#include <iterator>

#include "harness/DBC.hh"
#include "harness/Soft_Equivalence.hh"
#include "comm/global.hh"
#include "comm/Parallel_Unit_Test.hh"
#include "release/Release.hh"
#include "../Transfer_Map.hh"

using namespace std;
using nemesis::Parallel_Unit_Test;
using nemesis::soft_equiv;

using coupler::Transfer_Map;

int node  = 0;
int nodes = 0;

#define ITFAILS ut.failure(__LINE__);
#define UNIT_TEST(a) if (!(a)) ut.failure(__LINE__);

//---------------------------------------------------------------------------//
// TESTS
//---------------------------------------------------------------------------//

void map_test(Parallel_Unit_Test &ut)
{
    // Useful typedefs.
    typedef typename Transfer_Map::Map_Iterator    Map_Iterator;
    typedef typename Transfer_Map::Map_Pair        Map_Pair;
    typedef typename Transfer_Map::Set_Iterator    Set_Iterator;
    typedef typename Transfer_Map::Set_Pair        Set_Pair;

    // Make a map object with integer handles and ranks.
    Transfer_Map tmap;

    // Add domain pairs.
    tmap.add_domain_pair(1, 21);
    tmap.add_domain_pair(1, 32);
    tmap.add_domain_pair(1, 12);
    tmap.add_domain_pair(3, 2);
    tmap.add_domain_pair(4, 22);
    tmap.add_domain_pair(2, 54);
    tmap.add_domain_pair(3, 5);

    // Check the size of the domains.
    UNIT_TEST( tmap.domain_size(1) == 3 );
    UNIT_TEST( tmap.domain_size(2) == 1 );
    UNIT_TEST( tmap.domain_size(3) == 2 );
    UNIT_TEST( tmap.domain_size(4) == 1 );

    // Check the contents of the domains.
    Map_Pair domain_1 = tmap.domain(1);
    UNIT_TEST( std::distance(domain_1.first, domain_1.second) == 3 );
    Map_Iterator domain_it_1 = domain_1.first;
    UNIT_TEST( domain_it_1->second == 21 );
    ++domain_it_1;
    UNIT_TEST( domain_it_1->second == 32 );
    ++domain_it_1;
    UNIT_TEST( domain_it_1->second == 12 );

    Map_Pair domain_2 = tmap.domain(2);
    UNIT_TEST( std::distance(domain_2.first, domain_2.second) == 1 );
    Map_Iterator domain_it_2 = domain_2.first;
    UNIT_TEST( domain_it_2->second == 54 );

    Map_Pair domain_3 = tmap.domain(3);
    UNIT_TEST( std::distance(domain_3.first, domain_3.second) == 2 );
    Map_Iterator domain_it_3 = domain_3.first;
    UNIT_TEST( domain_it_3->second == 2 );
    ++domain_it_3;
    UNIT_TEST( domain_it_3->second == 5 );

    Map_Pair domain_4 = tmap.domain(4);
    UNIT_TEST( std::distance(domain_4.first, domain_4.second) == 1 );
    Map_Iterator domain_it_4 = domain_4.first;
    UNIT_TEST( domain_it_4->second == 22 );

    // Add range pairs.
    tmap.add_range_pair(8, 9);
    tmap.add_range_pair(32, 1);
    tmap.add_range_pair(8, 4);
    tmap.add_range_pair(8, 34);
    tmap.add_range_pair(32, 3);

    // Check the size of the ranges.
    UNIT_TEST( tmap.range_size(8) == 3 );
    UNIT_TEST( tmap.range_size(32) == 2 );

    // Check the contents of the ranges.
    Map_Pair range_8 = tmap.range(8);
    UNIT_TEST( std::distance(range_8.first,range_8.second) == 3 );
    Map_Iterator range_it_8 = range_8.first;
    UNIT_TEST( range_it_8->second == 9 );
    ++range_it_8;
    UNIT_TEST( range_it_8->second == 4 );
    ++range_it_8;
    UNIT_TEST( range_it_8->second == 34 );

    Map_Pair range_32 = tmap.range(32);
    UNIT_TEST( std::distance(range_32.first,range_32.second) == 2 );
    Map_Iterator range_it_32 = range_32.first;
    UNIT_TEST( range_it_32->second == 1 );
    ++range_it_32;
    UNIT_TEST( range_it_32->second == 3 );

    // Check the source and target sets.
    Set_Pair sources = tmap.sources();
    UNIT_TEST( std::distance(sources.first, sources.second) == 2 );
    Set_Iterator source_it = sources.first;
    UNIT_TEST( *source_it == 8 );
    ++source_it;
    UNIT_TEST( *source_it == 32 );

    Set_Pair targets = tmap.targets();
    UNIT_TEST( std::distance(targets.first, targets.second) == 4 );
    Set_Iterator target_it = targets.first;
    UNIT_TEST( *target_it == 1 );
    ++target_it;
    UNIT_TEST( *target_it == 2 );
    ++target_it;
    UNIT_TEST( *target_it == 3 );
    ++target_it;
    UNIT_TEST( *target_it == 4 );

    if (ut.numFails == 0)
    {
        std::ostringstream m;
        m << "Transfer_Map test passes on " << node;
        ut.passes( m.str() );
    }
}

//---------------------------------------------------------------------------//

int main(int argc, char *argv[])
{
    Parallel_Unit_Test ut(argc, argv, coupler::release);

    node  = nemesis::node();
    nodes = nemesis::nodes();

    try
    {
        // >>> UNIT TESTS
        int gpass = 0;
        int gfail = 0;

	map_test(ut);
	gpass += ut.numPasses;
	gfail += ut.numFails;
	ut.reset();

        // add up global passes and fails
        nemesis::global_sum(gpass);
        nemesis::global_sum(gfail);
	ut.numPasses = gpass;
        ut.numFails  = gfail;
    }
    catch (std::exception &err)
    {
        std::cout << "ERROR: While testing tstTransfer_Map, "
                  << err.what()
                  << endl;
        ut.numFails++;
    }
    catch( ... )
    {
        std::cout << "ERROR: While testing tstTransfer_Map, "
                  << "An unknown exception was thrown."
                  << endl;
        ut.numFails++;
    }
    return ut.numFails;
}

//---------------------------------------------------------------------------//
//                        end of tstTransfer_Map.cc
//---------------------------------------------------------------------------//
<|endoftext|>


<commit_before>// Copyright 2010 Google
// 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 "base/random.h"

namespace operations_research {

int32 ACMRandom::Next() {
  const int32 M = 2147483647L;   // 2^31-1
  const int32 A = 16807;
  // In effect, we are computing seed_ = (seed_ * A) % M, where M = 2^31-1
  uint32 lo = A * static_cast<int32>(seed_ & 0xFFFF);
  uint32 hi = A * static_cast<int32>(static_cast<uint32>(seed_) >> 16);
  lo += (hi & 0x7FFF) << 16;
  if (lo > M) {
    lo &= M;
    ++lo;
  }
  lo += hi >> 15;
  if (lo > M) {
    lo &= M;
    ++lo;
  }
  return (seed_ = static_cast<int32>(lo));
}

int32 ACMRandom::Uniform(int32 n) {
  return Next() % n;
}

int64 ACMRandom::Next64() {
  const int64 next = Next();
  return (next - 1) * 2147483646L + Next();
}

namespace {
static inline uint32 Word32At(const char *ptr) {
  return ((static_cast<uint32>(ptr[0])) +
          (static_cast<uint32>(ptr[1]) << 8) +
          (static_cast<uint32>(ptr[2]) << 16) +
          (static_cast<uint32>(ptr[3]) << 24));
}
}  // namespace

#if defined(__GNUC__) && defined(__linux__)
#include <linux/limits.h>
#endif
#if defined(_MSC_VER)
#include <windows.h>
#define PATH_MAX 4096
#endif

int32 ACMRandom::HostnamePidTimeSeed() {
  char name[PATH_MAX + 20];      // need 12 bytes for 3 'empty' uint32's
  assert(sizeof(name) - PATH_MAX > sizeof(uint32) * 3);

  if (gethostname(name, PATH_MAX) != 0) {
    strcpy(name, "default-hostname");
  }
  const int namelen = strlen(name);
  for (int i = 0; i < sizeof(uint32) * 3; ++i) {
    name[namelen + i] = '\0';   // so we mix 0's once we get to end-of-string
  }
#if defined(__GNUC__)
  uint32 a = getpid();
  struct timeval tv;
  gettimeofday(&tv, NULL);
  uint32 b = static_cast<uint32>((tv.tv_sec + tv.tv_usec) & 0xffffffff);
#elif defined(_MSC_VER)
  uint32 a = GetCurrentProcessId();
  uint32 b = GetTickCount();
#else  // Do not know what to do, returning 0.
  return 0;
#endif
  uint32 c = 0;
  for (int i = 0; i < namelen; i += sizeof(uint32) * 3) {
    a += Word32At(name + i);
    b += Word32At(name + i + sizeof(uint32));
    c += Word32At(name + i + sizeof(uint32) + sizeof(uint32));
    mix(a, b, c);
  }
  c += namelen;                      // one final mix
  mix(a,b,c);
  return static_cast<int32>(c);      // I guess the seed can be negative
}

int32 ACMRandom::DeterministicSeed() { return 0; }

}  // namespace operations_research
<commit_msg>fix random when seed == 0<commit_after>// Copyright 2010 Google
// 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 "base/random.h"

namespace operations_research {

int32 ACMRandom::Next() {
  if (seed_ == 0) {
    seed_ = 0x14fd4603;  // Arbitrary random constant
  }
  const int32 M = 2147483647L;   // 2^31-1
  const int32 A = 16807;
  // In effect, we are computing seed_ = (seed_ * A) % M, where M = 2^31-1
  uint32 lo = A * static_cast<int32>(seed_ & 0xFFFF);
  uint32 hi = A * static_cast<int32>(static_cast<uint32>(seed_) >> 16);
  lo += (hi & 0x7FFF) << 16;
  if (lo > M) {
    lo &= M;
    ++lo;
  }
  lo += hi >> 15;
  if (lo > M) {
    lo &= M;
    ++lo;
  }
  seed_ = static_cast<int32>(lo);
  return seed_;
}

int32 ACMRandom::Uniform(int32 n) {
  return Next() % n;
}

int64 ACMRandom::Next64() {
  const int64 next = Next();
  return (next - 1) * 2147483646L + Next();
}

namespace {
static inline uint32 Word32At(const char *ptr) {
  return ((static_cast<uint32>(ptr[0])) +
          (static_cast<uint32>(ptr[1]) << 8) +
          (static_cast<uint32>(ptr[2]) << 16) +
          (static_cast<uint32>(ptr[3]) << 24));
}
}  // namespace

#if defined(__GNUC__) && defined(__linux__)
#include <linux/limits.h>
#endif
#if defined(_MSC_VER)
#include <windows.h>
#define PATH_MAX 4096
#endif

int32 ACMRandom::HostnamePidTimeSeed() {
  char name[PATH_MAX + 20];      // need 12 bytes for 3 'empty' uint32's
  assert(sizeof(name) - PATH_MAX > sizeof(uint32) * 3);

  if (gethostname(name, PATH_MAX) != 0) {
    strcpy(name, "default-hostname");
  }
  const int namelen = strlen(name);
  for (int i = 0; i < sizeof(uint32) * 3; ++i) {
    name[namelen + i] = '\0';   // so we mix 0's once we get to end-of-string
  }
#if defined(__GNUC__)
  uint32 a = getpid();
  struct timeval tv;
  gettimeofday(&tv, NULL);
  uint32 b = static_cast<uint32>((tv.tv_sec + tv.tv_usec) & 0xffffffff);
#elif defined(_MSC_VER)
  uint32 a = GetCurrentProcessId();
  uint32 b = GetTickCount();
#else  // Do not know what to do, returning 0.
  return 0;
#endif
  uint32 c = 0;
  for (int i = 0; i < namelen; i += sizeof(uint32) * 3) {
    a += Word32At(name + i);
    b += Word32At(name + i + sizeof(uint32));
    c += Word32At(name + i + sizeof(uint32) + sizeof(uint32));
    mix(a, b, c);
  }
  c += namelen;                      // one final mix
  mix(a,b,c);
  return static_cast<int32>(c);      // I guess the seed can be negative
}

int32 ACMRandom::DeterministicSeed() { return 0; }

}  // namespace operations_research
<|endoftext|>


<commit_before>#include "gtest/gtest.h"

#include "paxos/ledger.hpp"

class LedgerUnitTest: public testing::Test
{
    virtual void SetUp()
    {
        DisableLogging();
    }
};

TEST_F(LedgerUnitTest, testAppendIncrementsTheSize)
{
    Ledger ledger(std::make_shared<VolatileQueue<Decree>>());

    ASSERT_EQ(ledger.Size(), 0);

    ledger.Append(Decree(Replica("an_author"), 1, "decree_contents", DecreeType::UserDecree));

    ASSERT_EQ(ledger.Size(), 1);
}

TEST_F(LedgerUnitTest, testRemoveDecrementsTheSize)
{
    Ledger ledger(std::make_shared<VolatileQueue<Decree>>());

    ledger.Append(Decree(Replica("an_author"), 1, "decree_contents", DecreeType::UserDecree));
    ledger.Remove();

    ASSERT_EQ(ledger.Size(), 0);
}

TEST_F(LedgerUnitTest, testEmptyHeadReturnsDefaultDecree)
{
    Ledger ledger(std::make_shared<VolatileQueue<Decree>>());
    Decree expected, actual = ledger.Head();

    ASSERT_EQ(expected.author.hostname, actual.author.hostname);
    ASSERT_EQ(expected.author.port, actual.author.port);
    ASSERT_EQ(expected.number, actual.number);
    ASSERT_EQ(expected.content, actual.content);
}

TEST_F(LedgerUnitTest, testEmptyTailReturnsDefaultDecree)
{
    Ledger ledger(std::make_shared<VolatileQueue<Decree>>());
    Decree expected, actual = ledger.Tail();

    ASSERT_EQ(expected.author.hostname, actual.author.hostname);
    ASSERT_EQ(expected.author.port, actual.author.port);
    ASSERT_EQ(expected.number, actual.number);
    ASSERT_EQ(expected.content, actual.content);
}

TEST_F(LedgerUnitTest, testEmptyNextWithFutureDecree)
{
    Ledger ledger(std::make_shared<VolatileQueue<Decree>>());
    Decree expected, actual = ledger.Next(Decree(Replica("b_author"), 2, "b_content", DecreeType::UserDecree));

    ASSERT_EQ(expected.author.hostname, actual.author.hostname);
    ASSERT_EQ(expected.author.port, actual.author.port);
    ASSERT_EQ(expected.number, actual.number);
    ASSERT_EQ(expected.content, actual.content);
}

TEST_F(LedgerUnitTest, testHeadWithMultipleDecrees)
{
    Ledger ledger(std::make_shared<VolatileQueue<Decree>>());
    ledger.Append(Decree(Replica("a_author"), 1, "a_content", DecreeType::UserDecree));
    ledger.Append(Decree(Replica("b_author"), 2, "b_content", DecreeType::UserDecree));

    Decree expected = Decree(Replica("a_author"), 1, "a_content", DecreeType::UserDecree), actual = ledger.Head();

    ASSERT_EQ(expected.author.hostname, actual.author.hostname);
    ASSERT_EQ(expected.author.port, actual.author.port);
    ASSERT_EQ(expected.number, actual.number);
    ASSERT_EQ(expected.content, actual.content);
}

TEST_F(LedgerUnitTest, testTailWithMultipleDecrees)
{
    Ledger ledger(std::make_shared<VolatileQueue<Decree>>());
    ledger.Append(Decree(Replica("a_author"), 1, "a_content", DecreeType::UserDecree));
    ledger.Append(Decree(Replica("b_author"), 2, "b_content", DecreeType::UserDecree));

    Decree expected = Decree(Replica("b_author"), 2, "b_content", DecreeType::UserDecree), actual = ledger.Tail();

    ASSERT_EQ(expected.author.hostname, actual.author.hostname);
    ASSERT_EQ(expected.author.port, actual.author.port);
    ASSERT_EQ(expected.number, actual.number);
    ASSERT_EQ(expected.content, actual.content);
}

TEST_F(LedgerUnitTest, testNextWithMultipleDecrees)
{
    Ledger ledger(std::make_shared<VolatileQueue<Decree>>());
    ledger.Append(Decree(Replica("a_author"), 1, "a_content", DecreeType::UserDecree));
    ledger.Append(Decree(Replica("b_author"), 2, "b_content", DecreeType::UserDecree));
    ledger.Append(Decree(Replica("c_author"), 3, "c_content", DecreeType::UserDecree));

    Decree expected = Decree(Replica("b_author"), 2, "b_content", DecreeType::UserDecree),
           actual = ledger.Next(Decree(Replica("a_author"), 1, "a_content", DecreeType::UserDecree));

    ASSERT_EQ(expected.author.hostname, actual.author.hostname);
    ASSERT_EQ(expected.author.port, actual.author.port);
    ASSERT_EQ(expected.number, actual.number);
    ASSERT_EQ(expected.content, actual.content);
}

TEST_F(LedgerUnitTest, testAppendIgnoresOutOfOrderDecrees)
{
    Ledger ledger(std::make_shared<VolatileQueue<Decree>>());
    ledger.Append(Decree(Replica("b_author"), 2, "b_content", DecreeType::UserDecree));
    ledger.Append(Decree(Replica("a_author"), 1, "a_content", DecreeType::UserDecree));

    ASSERT_EQ(ledger.Size(), 1);
}

TEST_F(LedgerUnitTest, testAppendIgnoresDuplicateDecrees)
{
    Ledger ledger(std::make_shared<VolatileQueue<Decree>>());
    ledger.Append(Decree(Replica("a_author"), 1, "a_content", DecreeType::UserDecree));
    ledger.Append(Decree(Replica("a_author"), 1, "a_content", DecreeType::UserDecree));

    ASSERT_EQ(ledger.Size(), 1);
}

TEST_F(LedgerUnitTest, testDecreeHandlerOnAppend)
{
    std::string concatenated_content;
    auto handler = [&](std::string entry) { concatenated_content += entry; };

    Ledger ledger(
        std::make_shared<VolatileQueue<Decree>>(),
        DecreeHandler(handler),
        DecreeHandler());
    ledger.Append(Decree(Replica("a_author"), 1, "AAAAA", DecreeType::UserDecree));
    ledger.Append(Decree(Replica("b_author"), 2, "BBBBB", DecreeType::UserDecree));

    ASSERT_EQ(concatenated_content, "AAAAABBBBB");
}
<commit_msg>Add unittest on ledger append of system decree<commit_after>#include "gtest/gtest.h"

#include "paxos/ledger.hpp"

class LedgerUnitTest: public testing::Test
{
    virtual void SetUp()
    {
        DisableLogging();
    }
};

TEST_F(LedgerUnitTest, testAppendIncrementsTheSize)
{
    Ledger ledger(std::make_shared<VolatileQueue<Decree>>());

    ASSERT_EQ(ledger.Size(), 0);

    ledger.Append(Decree(Replica("an_author"), 1, "decree_contents", DecreeType::UserDecree));

    ASSERT_EQ(ledger.Size(), 1);
}

TEST_F(LedgerUnitTest, testAppendSystemDecreeIncrementsTheSize)
{
    Ledger ledger(std::make_shared<VolatileQueue<Decree>>());

    ASSERT_EQ(ledger.Size(), 0);

    ledger.Append(Decree(Replica("an_author"), 1, "decree_contents", DecreeType::SystemDecree));

    ASSERT_EQ(ledger.Size(), 1);
}

TEST_F(LedgerUnitTest, testRemoveDecrementsTheSize)
{
    Ledger ledger(std::make_shared<VolatileQueue<Decree>>());

    ledger.Append(Decree(Replica("an_author"), 1, "decree_contents", DecreeType::UserDecree));
    ledger.Remove();

    ASSERT_EQ(ledger.Size(), 0);
}

TEST_F(LedgerUnitTest, testEmptyHeadReturnsDefaultDecree)
{
    Ledger ledger(std::make_shared<VolatileQueue<Decree>>());
    Decree expected, actual = ledger.Head();

    ASSERT_EQ(expected.author.hostname, actual.author.hostname);
    ASSERT_EQ(expected.author.port, actual.author.port);
    ASSERT_EQ(expected.number, actual.number);
    ASSERT_EQ(expected.content, actual.content);
}

TEST_F(LedgerUnitTest, testEmptyTailReturnsDefaultDecree)
{
    Ledger ledger(std::make_shared<VolatileQueue<Decree>>());
    Decree expected, actual = ledger.Tail();

    ASSERT_EQ(expected.author.hostname, actual.author.hostname);
    ASSERT_EQ(expected.author.port, actual.author.port);
    ASSERT_EQ(expected.number, actual.number);
    ASSERT_EQ(expected.content, actual.content);
}

TEST_F(LedgerUnitTest, testEmptyNextWithFutureDecree)
{
    Ledger ledger(std::make_shared<VolatileQueue<Decree>>());
    Decree expected, actual = ledger.Next(Decree(Replica("b_author"), 2, "b_content", DecreeType::UserDecree));

    ASSERT_EQ(expected.author.hostname, actual.author.hostname);
    ASSERT_EQ(expected.author.port, actual.author.port);
    ASSERT_EQ(expected.number, actual.number);
    ASSERT_EQ(expected.content, actual.content);
}

TEST_F(LedgerUnitTest, testHeadWithMultipleDecrees)
{
    Ledger ledger(std::make_shared<VolatileQueue<Decree>>());
    ledger.Append(Decree(Replica("a_author"), 1, "a_content", DecreeType::UserDecree));
    ledger.Append(Decree(Replica("b_author"), 2, "b_content", DecreeType::UserDecree));

    Decree expected = Decree(Replica("a_author"), 1, "a_content", DecreeType::UserDecree), actual = ledger.Head();

    ASSERT_EQ(expected.author.hostname, actual.author.hostname);
    ASSERT_EQ(expected.author.port, actual.author.port);
    ASSERT_EQ(expected.number, actual.number);
    ASSERT_EQ(expected.content, actual.content);
}

TEST_F(LedgerUnitTest, testTailWithMultipleDecrees)
{
    Ledger ledger(std::make_shared<VolatileQueue<Decree>>());
    ledger.Append(Decree(Replica("a_author"), 1, "a_content", DecreeType::UserDecree));
    ledger.Append(Decree(Replica("b_author"), 2, "b_content", DecreeType::UserDecree));

    Decree expected = Decree(Replica("b_author"), 2, "b_content", DecreeType::UserDecree), actual = ledger.Tail();

    ASSERT_EQ(expected.author.hostname, actual.author.hostname);
    ASSERT_EQ(expected.author.port, actual.author.port);
    ASSERT_EQ(expected.number, actual.number);
    ASSERT_EQ(expected.content, actual.content);
}

TEST_F(LedgerUnitTest, testNextWithMultipleDecrees)
{
    Ledger ledger(std::make_shared<VolatileQueue<Decree>>());
    ledger.Append(Decree(Replica("a_author"), 1, "a_content", DecreeType::UserDecree));
    ledger.Append(Decree(Replica("b_author"), 2, "b_content", DecreeType::UserDecree));
    ledger.Append(Decree(Replica("c_author"), 3, "c_content", DecreeType::UserDecree));

    Decree expected = Decree(Replica("b_author"), 2, "b_content", DecreeType::UserDecree),
           actual = ledger.Next(Decree(Replica("a_author"), 1, "a_content", DecreeType::UserDecree));

    ASSERT_EQ(expected.author.hostname, actual.author.hostname);
    ASSERT_EQ(expected.author.port, actual.author.port);
    ASSERT_EQ(expected.number, actual.number);
    ASSERT_EQ(expected.content, actual.content);
}

TEST_F(LedgerUnitTest, testAppendIgnoresOutOfOrderDecrees)
{
    Ledger ledger(std::make_shared<VolatileQueue<Decree>>());
    ledger.Append(Decree(Replica("b_author"), 2, "b_content", DecreeType::UserDecree));
    ledger.Append(Decree(Replica("a_author"), 1, "a_content", DecreeType::UserDecree));

    ASSERT_EQ(ledger.Size(), 1);
}

TEST_F(LedgerUnitTest, testAppendIgnoresDuplicateDecrees)
{
    Ledger ledger(std::make_shared<VolatileQueue<Decree>>());
    ledger.Append(Decree(Replica("a_author"), 1, "a_content", DecreeType::UserDecree));
    ledger.Append(Decree(Replica("a_author"), 1, "a_content", DecreeType::UserDecree));

    ASSERT_EQ(ledger.Size(), 1);
}

TEST_F(LedgerUnitTest, testDecreeHandlerOnAppend)
{
    std::string concatenated_content;
    auto handler = [&](std::string entry) { concatenated_content += entry; };

    Ledger ledger(
        std::make_shared<VolatileQueue<Decree>>(),
        DecreeHandler(handler),
        DecreeHandler());
    ledger.Append(Decree(Replica("a_author"), 1, "AAAAA", DecreeType::UserDecree));
    ledger.Append(Decree(Replica("b_author"), 2, "BBBBB", DecreeType::UserDecree));

    ASSERT_EQ(concatenated_content, "AAAAABBBBB");
}
<|endoftext|>


<commit_before>/*
Copyright (c) 2014-2016 AscEmu Team <http://www.ascemu.org/>
This file is released under the MIT license. See README-MIT for more information.
*/

#include "StdAfx.h"

SpellInfo::SpellInfo()
{
    Id = 0;
    Category = 0;
    DispelType = 0;
    MechanicsType = 0;
    Attributes = 0;
    AttributesEx = 0;
    AttributesExB = 0;
    AttributesExC = 0;
    AttributesExD = 0;
    AttributesExE = 0;
    AttributesExF = 0;
    AttributesExG = 0;
    RequiredShapeShift = 0;
    ShapeshiftExclude = 0;
    Targets = 0;
    TargetCreatureType = 0;
    RequiresSpellFocus = 0;
    FacingCasterFlags = 0;
    CasterAuraState = 0;
    TargetAuraState = 0;
    CasterAuraStateNot = 0;
    TargetAuraStateNot = 0;
    casterAuraSpell = 0;
    targetAuraSpell = 0;
    casterAuraSpellNot = 0;

    CustomFlags = 0;

    for (uint8 i = 0; i < MAX_SPELL_EFFECTS; i++)
        EffectCustomFlag[i] = 0;

    SpellFactoryFunc = NULL;
    AuraFactoryFunc = NULL;
    custom_proc_interval = 0;
    custom_BGR_one_buff_on_target = 0;
    custom_BGR_one_buff_from_caster_on_self = 0;
    custom_c_is_flags = 0;
    custom_RankNumber = 0;
    custom_NameHash = 0;
    custom_ThreatForSpell = 0;
    custom_ThreatForSpellCoef = 0;
    custom_spell_coef_flags = 0;
    custom_base_range_or_radius_sqr = 0;
    cone_width = 0;
    casttime_coef = 0;
    fixed_dddhcoef = 0;
    fixed_hotdotcoef = 0;
    Dspell_coef_override = 0;
    OTspell_coef_override = 0;
    ai_target_type = 0;
    custom_self_cast_only = false;
    custom_apply_on_shapeshift_change = false;
    custom_always_apply = false;
    custom_is_melee_spell = false;
    custom_is_ranged_spell = false;

    custom_SchoolMask = 0;
    SpellVisual = 0;
    field114 = 0;
    spellIconID = 0;
    activeIconID = 0;
    spellPriority = 0;
    Name = "";
    Rank = "";
    Description = "";
    BuffDescription = "";
    ManaCostPercentage = 0;
    StartRecoveryCategory = 0;
    StartRecoveryTime = 0;
    MaxTargetLevel = 0;
    SpellFamilyName = 0;
    MaxTargets = 0;
    Spell_Dmg_Type = 0;
    PreventionType = 0;
    StanceBarOrder = 0;
    MinFactionID = 0;
    MinReputation = 0;
    RequiredAuraVision = 0;
    RequiresAreaId = 0;
    School = 0;
    RuneCostID = 0;
    SpellDifficultyID = 0;
    custom_DiminishStatus = 0;
    targetAuraSpellNot = 0;
    CastingTimeIndex = 0;
    RecoveryTime = 0;
    CategoryRecoveryTime = 0;
    InterruptFlags = 0;
    AuraInterruptFlags = 0;
    ChannelInterruptFlags = 0;
    procFlags = 0;
    procChance = 0;
    procCharges = 0;
    maxLevel = 0;
    baseLevel = 0;
    spellLevel = 0;
    DurationIndex = 0;
    powerType = 0;
    manaCost = 0;
    manaCostPerlevel = 0;
    manaPerSecond = 0;
    manaPerSecondPerLevel = 0;
    rangeIndex = 0;
    speed = 0;
    modalNextSpell = 0;
    maxstack = 0;
    EquippedItemClass = 0;
    EquippedItemSubClass = 0;
    RequiredItemFlags = 0;
}

SpellInfo::~SpellInfo() {}

bool SpellInfo::HasEffect(uint32 effect)
{
    for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
        if (Effect[i] == effect)
            return true;

    return false;
}

bool SpellInfo::HasCustomFlagForEffect(uint32 effect, uint32 flag)
{
    if (effect >= MAX_SPELL_EFFECTS)
        return false;

    if ((EffectCustomFlag[effect] & flag) != 0)
        return true;
    else
        return false;
}

bool SpellInfo::IsPassive()
{
    return Attributes & ATTRIBUTES_PASSIVE;
}

bool SpellInfo::IsProfession()
{
    for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
    {
        if (Effect[i] == SPELL_EFFECT_SKILL)
        {
            uint32 skill = EffectMiscValue[i];

            //Profession skill
            if (skill == SKILL_FISHING || skill == SKILL_COOKING || skill == SKILL_FIRST_AID)
                return true;

            if (IsPrimaryProfessionSkill(skill))
                return true;
        }
    }
    return false;
}

bool SpellInfo::IsPrimaryProfession()
{
    for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
    {
        if (Effect[i] == SPELL_EFFECT_SKILL)
        {
            uint32 skill = EffectMiscValue[i];

            if (IsPrimaryProfessionSkill(skill))
                return true;
        }
    }
    return false;
}

bool SpellInfo::IsPrimaryProfessionSkill(uint32 skill_id)
{
    if (DBC::Structures::SkillLineEntry const* skill_line = sSkillLineStore.LookupEntry(skill_id))
        if (skill_line && skill_line->type == SKILL_TYPE_PROFESSION)
            return true;

    return false;
}

bool SpellInfo::IsDeathPersistent()
{
    return AttributesExC & ATTRIBUTESEXC_CAN_PERSIST_AND_CASTED_WHILE_DEAD;
}

bool SpellInfo::AppliesAreaAura(uint32 aura)
{
    for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
    {
        if ((Effect[i] == 6 ||        /// SPELL_EFFECT_APPLY_GROUP_AREA_AURA <-wrong
             Effect[i] == SPELL_EFFECT_PERSISTENT_AREA_AURA ||
             Effect[i] == SPELL_EFFECT_APPLY_GROUP_AREA_AURA ||
             Effect[i] == SPELL_EFFECT_APPLY_RAID_AREA_AURA ||
             Effect[i] == SPELL_EFFECT_APPLY_PET_AREA_AURA ||
             Effect[i] == SPELL_EFFECT_APPLY_FRIEND_AREA_AURA ||
             Effect[i] == SPELL_EFFECT_APPLY_ENEMY_AREA_AURA ||
             Effect[i] == SPELL_EFFECT_APPLY_OWNER_AREA_AURA) &&
            EffectApplyAuraName[i] == aura)
            return true;
    }

    return false;
}

uint32 SpellInfo::GetAreaAuraEffectId()
{
    for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
    {
        if (Effect[i] == SPELL_EFFECT_APPLY_GROUP_AREA_AURA ||
            Effect[i] == SPELL_EFFECT_APPLY_RAID_AREA_AURA ||
            Effect[i] == SPELL_EFFECT_APPLY_PET_AREA_AURA ||
            Effect[i] == SPELL_EFFECT_APPLY_FRIEND_AREA_AURA ||
            Effect[i] == SPELL_EFFECT_APPLY_ENEMY_AREA_AURA ||
            Effect[i] == SPELL_EFFECT_APPLY_OWNER_AREA_AURA)
            return Effect[i];
    }

    return 0;
}
<commit_msg>Feedback from danko<commit_after>/*
Copyright (c) 2014-2016 AscEmu Team <http://www.ascemu.org/>
This file is released under the MIT license. See README-MIT for more information.
*/

#include "StdAfx.h"

SpellInfo::SpellInfo()
{
    Id = 0;
    Category = 0;
    DispelType = 0;
    MechanicsType = 0;
    Attributes = 0;
    AttributesEx = 0;
    AttributesExB = 0;
    AttributesExC = 0;
    AttributesExD = 0;
    AttributesExE = 0;
    AttributesExF = 0;
    AttributesExG = 0;
    RequiredShapeShift = 0;
    ShapeshiftExclude = 0;
    Targets = 0;
    TargetCreatureType = 0;
    RequiresSpellFocus = 0;
    FacingCasterFlags = 0;
    CasterAuraState = 0;
    TargetAuraState = 0;
    CasterAuraStateNot = 0;
    TargetAuraStateNot = 0;
    casterAuraSpell = 0;
    targetAuraSpell = 0;
    casterAuraSpellNot = 0;

    CustomFlags = 0;

    for (uint8 i = 0; i < MAX_SPELL_EFFECTS; i++)
        EffectCustomFlag[i] = 0;

    SpellFactoryFunc = NULL;
    AuraFactoryFunc = NULL;
    custom_proc_interval = 0;
    custom_BGR_one_buff_on_target = 0;
    custom_BGR_one_buff_from_caster_on_self = 0;
    custom_c_is_flags = 0;
    custom_RankNumber = 0;
    custom_NameHash = 0;
    custom_ThreatForSpell = 0;
    custom_ThreatForSpellCoef = 0;
    custom_spell_coef_flags = 0;
    custom_base_range_or_radius_sqr = 0;
    cone_width = 0;
    casttime_coef = 0;
    fixed_dddhcoef = 0;
    fixed_hotdotcoef = 0;
    Dspell_coef_override = 0;
    OTspell_coef_override = 0;
    ai_target_type = 0;
    custom_self_cast_only = false;
    custom_apply_on_shapeshift_change = false;
    custom_always_apply = false;
    custom_is_melee_spell = false;
    custom_is_ranged_spell = false;

    custom_SchoolMask = 0;
    SpellVisual = 0;
    field114 = 0;
    spellIconID = 0;
    activeIconID = 0;
    spellPriority = 0;
    Name = "";
    Rank = "";
    Description = "";
    BuffDescription = "";
    ManaCostPercentage = 0;
    StartRecoveryCategory = 0;
    StartRecoveryTime = 0;
    MaxTargetLevel = 0;
    SpellFamilyName = 0;
    MaxTargets = 0;
    Spell_Dmg_Type = 0;
    PreventionType = 0;
    StanceBarOrder = 0;
    MinFactionID = 0;
    MinReputation = 0;
    RequiredAuraVision = 0;
    RequiresAreaId = 0;
    School = 0;
    RuneCostID = 0;
    SpellDifficultyID = 0;
    custom_DiminishStatus = 0;
    targetAuraSpellNot = 0;
    CastingTimeIndex = 0;
    RecoveryTime = 0;
    CategoryRecoveryTime = 0;
    InterruptFlags = 0;
    AuraInterruptFlags = 0;
    ChannelInterruptFlags = 0;
    procFlags = 0;
    procChance = 0;
    procCharges = 0;
    maxLevel = 0;
    baseLevel = 0;
    spellLevel = 0;
    DurationIndex = 0;
    powerType = 0;
    manaCost = 0;
    manaCostPerlevel = 0;
    manaPerSecond = 0;
    manaPerSecondPerLevel = 0;
    rangeIndex = 0;
    speed = 0;
    modalNextSpell = 0;
    maxstack = 0;
    EquippedItemClass = 0;
    EquippedItemSubClass = 0;
    RequiredItemFlags = 0;
}

SpellInfo::~SpellInfo() {}

bool SpellInfo::HasEffect(uint32 effect)
{
    for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
        if (Effect[i] == effect)
            return true;

    return false;
}

bool SpellInfo::HasCustomFlagForEffect(uint32 effect, uint32 flag)
{
    if (effect >= MAX_SPELL_EFFECTS)
        return false;

    if ((EffectCustomFlag[effect] & flag) != 0)
        return true;
    else
        return false;
}

bool SpellInfo::IsPassive()
{
    return Attributes & ATTRIBUTES_PASSIVE;
}

bool SpellInfo::IsProfession()
{
    for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
    {
        if (Effect[i] == SPELL_EFFECT_SKILL)
        {
            uint32 skill = EffectMiscValue[i];

            //Profession skill
            if (skill == SKILL_FISHING || skill == SKILL_COOKING || skill == SKILL_FIRST_AID)
                return true;

            if (IsPrimaryProfessionSkill(skill))
                return true;
        }
    }
    return false;
}

bool SpellInfo::IsPrimaryProfession()
{
    for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
    {
        if (Effect[i] == SPELL_EFFECT_SKILL)
        {
            uint32 skill = EffectMiscValue[i];

            if (IsPrimaryProfessionSkill(skill))
                return true;
        }
    }
    return false;
}

bool SpellInfo::IsPrimaryProfessionSkill(uint32 skill_id)
{
    if (DBC::Structures::SkillLineEntry const* skill_line = sSkillLineStore.LookupEntry(skill_id))
        if (skill_line && skill_line->type == SKILL_TYPE_PROFESSION)
            return true;

    return false;
}

bool SpellInfo::IsDeathPersistent()
{
    return AttributesExC & ATTRIBUTESEXC_CAN_PERSIST_AND_CASTED_WHILE_DEAD;
}

bool SpellInfo::AppliesAreaAura(uint32 aura)
{
    for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
    {
        if ((Effect[i] == SPELL_EFFECT_PERSISTENT_AREA_AURA ||
             Effect[i] == SPELL_EFFECT_APPLY_GROUP_AREA_AURA ||
             Effect[i] == SPELL_EFFECT_APPLY_RAID_AREA_AURA ||
             Effect[i] == SPELL_EFFECT_APPLY_PET_AREA_AURA ||
             Effect[i] == SPELL_EFFECT_APPLY_FRIEND_AREA_AURA ||
             Effect[i] == SPELL_EFFECT_APPLY_ENEMY_AREA_AURA ||
             Effect[i] == SPELL_EFFECT_APPLY_OWNER_AREA_AURA) &&
            EffectApplyAuraName[i] == aura)
            return true;
    }

    return false;
}

uint32 SpellInfo::GetAreaAuraEffectId()
{
    for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
    {
        if (Effect[i] == SPELL_EFFECT_APPLY_GROUP_AREA_AURA ||
            Effect[i] == SPELL_EFFECT_APPLY_RAID_AREA_AURA ||
            Effect[i] == SPELL_EFFECT_APPLY_PET_AREA_AURA ||
            Effect[i] == SPELL_EFFECT_APPLY_FRIEND_AREA_AURA ||
            Effect[i] == SPELL_EFFECT_APPLY_ENEMY_AREA_AURA ||
            Effect[i] == SPELL_EFFECT_APPLY_OWNER_AREA_AURA)
            return Effect[i];
    }

    return 0;
}
<|endoftext|>


<commit_before>// Copyright (c) 2009-2017 The Regents of the University of Michigan
// This file is part of the HOOMD-blue project, released under the BSD 3-Clause License.

// Maintainer: joaander

/*! \file NeighborListBinned.cc
    \brief Defines NeighborListBinned
*/

#include "NeighborListBinned.h"

#ifdef ENABLE_MPI
#include "hoomd/Communicator.h"
#endif

using namespace std;
namespace py = pybind11;

NeighborListBinned::NeighborListBinned(std::shared_ptr<SystemDefinition> sysdef,
                                       Scalar r_cut,
                                       Scalar r_buff,
                                       std::shared_ptr<CellList> cl)
    : NeighborList(sysdef, r_cut, r_buff), m_cl(cl)
    {
    m_exec_conf->msg->notice(5) << "Constructing NeighborListBinned" << endl;

    // create a default cell list if one was not specified
    if (!m_cl)
        m_cl = std::shared_ptr<CellList>(new CellList(sysdef));

    m_cl->setRadius(1);
    m_cl->setComputeTDB(false);
    m_cl->setFlagIndex();

    // call this class's special setRCut
    setRCut(r_cut, r_buff);
    }

NeighborListBinned::~NeighborListBinned()
    {
    m_exec_conf->msg->notice(5) << "Destroying NeighborListBinned" << endl;
    }

void NeighborListBinned::setRCut(Scalar r_cut, Scalar r_buff)
    {
    NeighborList::setRCut(r_cut, r_buff);
    Scalar rmax = getMaxRCut() + m_r_buff;
    if (m_diameter_shift)
        rmax += m_d_max - Scalar(1.0);

    m_cl->setNominalWidth(rmax);
    }

void NeighborListBinned::setRCutPair(unsigned int typ1, unsigned int typ2, Scalar r_cut)
    {
    NeighborList::setRCutPair(typ1,typ2,r_cut);

    Scalar rmax = getMaxRCut() + m_r_buff;
    if (m_diameter_shift)
        rmax += m_d_max - Scalar(1.0);

    m_cl->setNominalWidth(rmax);
    }

void NeighborListBinned::setMaximumDiameter(Scalar d_max)
    {
    NeighborList::setMaximumDiameter(d_max);

    // need to update the cell list settings appropriately
    Scalar rmax = getMaxRCut() + m_r_buff;
    if (m_diameter_shift)
        rmax += m_d_max - Scalar(1.0);

    m_cl->setNominalWidth(rmax);
    }

void NeighborListBinned::buildNlist(unsigned int timestep)
    {
    m_cl->compute(timestep);

    uint3 dim = m_cl->getDim();
    Scalar3 ghost_width = m_cl->getGhostWidth();

    if (m_prof)
        m_prof->push(m_exec_conf, "compute");

    // acquire the particle data and box dimension
    ArrayHandle<Scalar4> h_pos(m_pdata->getPositions(), access_location::host, access_mode::read);
    ArrayHandle<unsigned int> h_body(m_pdata->getBodies(), access_location::host, access_mode::read);
    ArrayHandle<Scalar> h_diameter(m_pdata->getDiameters(), access_location::host, access_mode::read);
    ArrayHandle<int3> h_image(m_pdata->getImages(), access_location::host, access_mode::read);

    const BoxDim& box = m_pdata->getBox();
    Scalar3 nearest_plane_distance = box.getNearestPlaneDistance();

    // validate that the cutoff fits inside the box
    Scalar rmax = getMaxRCut() + m_r_buff;
    if (m_diameter_shift)
        rmax += m_d_max - Scalar(1.0);

    if (m_filter_body)
        {
        // add the maximum diameter of all composite particles
        Scalar max_d_comp = m_pdata->getMaxCompositeParticleDiameter();
        rmax += 0.5*max_d_comp;
        }

    if ((box.getPeriodic().x && nearest_plane_distance.x <= rmax * 2.0) ||
        (box.getPeriodic().y && nearest_plane_distance.y <= rmax * 2.0) ||
        (this->m_sysdef->getNDimensions() == 3 && box.getPeriodic().z && nearest_plane_distance.z <= rmax * 2.0))
        {
        m_exec_conf->msg->error() << "nlist: Simulation box is too small! Particles would be interacting with themselves." << endl;
        throw runtime_error("Error updating neighborlist bins");
        }

    // access the rlist data
    ArrayHandle<Scalar> h_r_cut(m_r_cut, access_location::host, access_mode::read);
    ArrayHandle<Scalar> h_r_listsq(m_r_listsq, access_location::host, access_mode::read);

    // access the cell list data arrays
    ArrayHandle<unsigned int> h_cell_size(m_cl->getCellSizeArray(), access_location::host, access_mode::read);
    ArrayHandle<Scalar4> h_cell_xyzf(m_cl->getXYZFArray(), access_location::host, access_mode::read);
    ArrayHandle<unsigned int> h_cell_adj(m_cl->getCellAdjArray(), access_location::host, access_mode::read);

    // access the neighbor list data
    ArrayHandle<unsigned int> h_head_list(m_head_list, access_location::host, access_mode::read);
    ArrayHandle<unsigned int> h_Nmax(m_Nmax, access_location::host, access_mode::read);
    ArrayHandle<unsigned int> h_conditions(m_conditions, access_location::host, access_mode::readwrite);
    ArrayHandle<unsigned int> h_nlist(m_nlist, access_location::host, access_mode::overwrite);
    ArrayHandle<unsigned int> h_n_neigh(m_n_neigh, access_location::host, access_mode::overwrite);

    // access indexers
    Index3D ci = m_cl->getCellIndexer();
    Index2D cli = m_cl->getCellListIndexer();
    Index2D cadji = m_cl->getCellAdjIndexer();

    // get periodic flags
    uchar3 periodic = box.getPeriodic();

    // for each local particle
    unsigned int nparticles = m_pdata->getN();

    for (int i = 0; i < (int)nparticles; i++)
        {
        unsigned int cur_n_neigh = 0;

        const Scalar3 my_pos = make_scalar3(h_pos.data[i].x, h_pos.data[i].y, h_pos.data[i].z);
        const unsigned int type_i = __scalar_as_int(h_pos.data[i].w);
        const unsigned int body_i = h_body.data[i];
        const Scalar diam_i = h_diameter.data[i];

        const unsigned int Nmax_i = h_Nmax.data[type_i];
        const unsigned int head_idx_i = h_head_list.data[i];

        // find the bin each particle belongs in
        Scalar3 f = box.makeFraction(my_pos,ghost_width);
        int ib = (unsigned int)(f.x * dim.x);
        int jb = (unsigned int)(f.y * dim.y);
        int kb = (unsigned int)(f.z * dim.z);

        // need to handle the case where the particle is exactly at the box hi
        if (ib == (int)dim.x && periodic.x)
            ib = 0;
        if (jb == (int)dim.y && periodic.y)
            jb = 0;
        if (kb == (int)dim.z && periodic.z)
            kb = 0;

        // identify the bin
        unsigned int my_cell = ci(ib,jb,kb);

        // loop through all neighboring bins
        for (unsigned int cur_adj = 0; cur_adj < cadji.getW(); cur_adj++)
            {
            unsigned int neigh_cell = h_cell_adj.data[cadji(cur_adj, my_cell)];

            // check against all the particles in that neighboring bin to see if it is a neighbor
            unsigned int size = h_cell_size.data[neigh_cell];
            for (unsigned int cur_offset = 0; cur_offset < size; cur_offset++)
                {
                Scalar4& cur_xyzf = h_cell_xyzf.data[cli(cur_offset, neigh_cell)];
                unsigned int cur_neigh = __scalar_as_int(cur_xyzf.w);

                // get the current neighbor type from the position data (will use tdb on the GPU)
                unsigned int cur_neigh_type = __scalar_as_int(h_pos.data[cur_neigh].w);
                Scalar r_cut = h_r_cut.data[m_typpair_idx(type_i,cur_neigh_type)];

                // automatically exclude particles without a distance check when:
                // (1) they are the same particle, or
                // (2) the r_cut(i,j) indicates to skip, or
                // (3) they are in the same body
                bool excluded = ((i == (int)cur_neigh) || (r_cut <= Scalar(0.0)));

                Scalar3 neigh_pos = make_scalar3(cur_xyzf.x, cur_xyzf.y, cur_xyzf.z);
                Scalar3 dx = my_pos - neigh_pos;
                dx = box.minImage(dx);

                if (m_filter_body && body_i != NO_BODY && body_i == h_body.data[cur_neigh])
                    {
                    Scalar3 rtest = my_pos - dx;
                    int3 test_img = h_image.data[i];
                    int3 img_j = h_image.data[cur_neigh];
                    box.wrap(rtest, test_img);
                    // if the images match, then it is the particle in the same image of the body
                    // so it should be excluded
                    excluded |= (test_img == img_j);
                    }

                if (excluded)
                    continue;

                Scalar r_list = r_cut + m_r_buff;
                Scalar sqshift = Scalar(0.0);
                if (m_diameter_shift)
                    {
                    const Scalar delta = (diam_i + h_diameter.data[cur_neigh]) * Scalar(0.5) - Scalar(1.0);
                    // r^2 < (r_list + delta)^2
                    // r^2 < r_listsq + delta^2 + 2*r_list*delta
                    sqshift = (delta + Scalar(2.0) * r_list) * delta;
                    }

                Scalar dr_sq = dot(dx,dx);

                // move the squared rlist by the diameter shift if necessary
                Scalar r_listsq = h_r_listsq.data[m_typpair_idx(type_i,cur_neigh_type)];
                if (dr_sq <= (r_listsq + sqshift) && !excluded)
                    {
                    if (m_storage_mode == full || i < (int)cur_neigh)
                        {
                        // local neighbor
                        if (cur_n_neigh < Nmax_i)
                            {
                            h_nlist.data[head_idx_i + cur_n_neigh] = cur_neigh;
                            }
                        else
                            h_conditions.data[type_i] = max(h_conditions.data[type_i], cur_n_neigh+1);

                        cur_n_neigh++;
                        }
                    }
                }
            }

        h_n_neigh.data[i] = cur_n_neigh;
        }

    if (m_prof)
        m_prof->pop(m_exec_conf);
    }

void export_NeighborListBinned(py::module& m)
    {
    py::class_<NeighborListBinned, std::shared_ptr<NeighborListBinned> >(m, "NeighborListBinned", py::base<NeighborList>())
    .def(py::init< std::shared_ptr<SystemDefinition>, Scalar, Scalar, std::shared_ptr<CellList> >())
                     ;
    }
<commit_msg>Revert "implement self interaction check in NeighborListBinned base class"<commit_after>// Copyright (c) 2009-2017 The Regents of the University of Michigan
// This file is part of the HOOMD-blue project, released under the BSD 3-Clause License.

// Maintainer: joaander

/*! \file NeighborListBinned.cc
    \brief Defines NeighborListBinned
*/

#include "NeighborListBinned.h"

#ifdef ENABLE_MPI
#include "hoomd/Communicator.h"
#endif

using namespace std;
namespace py = pybind11;

NeighborListBinned::NeighborListBinned(std::shared_ptr<SystemDefinition> sysdef,
                                       Scalar r_cut,
                                       Scalar r_buff,
                                       std::shared_ptr<CellList> cl)
    : NeighborList(sysdef, r_cut, r_buff), m_cl(cl)
    {
    m_exec_conf->msg->notice(5) << "Constructing NeighborListBinned" << endl;

    // create a default cell list if one was not specified
    if (!m_cl)
        m_cl = std::shared_ptr<CellList>(new CellList(sysdef));

    m_cl->setRadius(1);
    m_cl->setComputeTDB(false);
    m_cl->setFlagIndex();

    // call this class's special setRCut
    setRCut(r_cut, r_buff);
    }

NeighborListBinned::~NeighborListBinned()
    {
    m_exec_conf->msg->notice(5) << "Destroying NeighborListBinned" << endl;
    }

void NeighborListBinned::setRCut(Scalar r_cut, Scalar r_buff)
    {
    NeighborList::setRCut(r_cut, r_buff);
    Scalar rmax = getMaxRCut() + m_r_buff;
    if (m_diameter_shift)
        rmax += m_d_max - Scalar(1.0);

    m_cl->setNominalWidth(rmax);
    }

void NeighborListBinned::setRCutPair(unsigned int typ1, unsigned int typ2, Scalar r_cut)
    {
    NeighborList::setRCutPair(typ1,typ2,r_cut);

    Scalar rmax = getMaxRCut() + m_r_buff;
    if (m_diameter_shift)
        rmax += m_d_max - Scalar(1.0);

    m_cl->setNominalWidth(rmax);
    }

void NeighborListBinned::setMaximumDiameter(Scalar d_max)
    {
    NeighborList::setMaximumDiameter(d_max);

    // need to update the cell list settings appropriately
    Scalar rmax = getMaxRCut() + m_r_buff;
    if (m_diameter_shift)
        rmax += m_d_max - Scalar(1.0);

    m_cl->setNominalWidth(rmax);
    }

void NeighborListBinned::buildNlist(unsigned int timestep)
    {
    m_cl->compute(timestep);

    uint3 dim = m_cl->getDim();
    Scalar3 ghost_width = m_cl->getGhostWidth();

    if (m_prof)
        m_prof->push(m_exec_conf, "compute");

    // acquire the particle data and box dimension
    ArrayHandle<Scalar4> h_pos(m_pdata->getPositions(), access_location::host, access_mode::read);
    ArrayHandle<unsigned int> h_body(m_pdata->getBodies(), access_location::host, access_mode::read);
    ArrayHandle<Scalar> h_diameter(m_pdata->getDiameters(), access_location::host, access_mode::read);

    const BoxDim& box = m_pdata->getBox();
    Scalar3 nearest_plane_distance = box.getNearestPlaneDistance();

    // validate that the cutoff fits inside the box
    Scalar rmax = getMaxRCut() + m_r_buff;
    if (m_diameter_shift)
        rmax += m_d_max - Scalar(1.0);

    if (m_filter_body)
        {
        // add the maximum diameter of all composite particles
        Scalar max_d_comp = m_pdata->getMaxCompositeParticleDiameter();
        rmax += 0.5*max_d_comp;
        }

    if ((box.getPeriodic().x && nearest_plane_distance.x <= rmax * 2.0) ||
        (box.getPeriodic().y && nearest_plane_distance.y <= rmax * 2.0) ||
        (this->m_sysdef->getNDimensions() == 3 && box.getPeriodic().z && nearest_plane_distance.z <= rmax * 2.0))
        {
        m_exec_conf->msg->error() << "nlist: Simulation box is too small! Particles would be interacting with themselves." << endl;
        throw runtime_error("Error updating neighborlist bins");
        }

    // access the rlist data
    ArrayHandle<Scalar> h_r_cut(m_r_cut, access_location::host, access_mode::read);
    ArrayHandle<Scalar> h_r_listsq(m_r_listsq, access_location::host, access_mode::read);

    // access the cell list data arrays
    ArrayHandle<unsigned int> h_cell_size(m_cl->getCellSizeArray(), access_location::host, access_mode::read);
    ArrayHandle<Scalar4> h_cell_xyzf(m_cl->getXYZFArray(), access_location::host, access_mode::read);
    ArrayHandle<unsigned int> h_cell_adj(m_cl->getCellAdjArray(), access_location::host, access_mode::read);

    // access the neighbor list data
    ArrayHandle<unsigned int> h_head_list(m_head_list, access_location::host, access_mode::read);
    ArrayHandle<unsigned int> h_Nmax(m_Nmax, access_location::host, access_mode::read);
    ArrayHandle<unsigned int> h_conditions(m_conditions, access_location::host, access_mode::readwrite);
    ArrayHandle<unsigned int> h_nlist(m_nlist, access_location::host, access_mode::overwrite);
    ArrayHandle<unsigned int> h_n_neigh(m_n_neigh, access_location::host, access_mode::overwrite);

    // access indexers
    Index3D ci = m_cl->getCellIndexer();
    Index2D cli = m_cl->getCellListIndexer();
    Index2D cadji = m_cl->getCellAdjIndexer();

    // get periodic flags
    uchar3 periodic = box.getPeriodic();

    // for each local particle
    unsigned int nparticles = m_pdata->getN();

    for (int i = 0; i < (int)nparticles; i++)
        {
        unsigned int cur_n_neigh = 0;

        const Scalar3 my_pos = make_scalar3(h_pos.data[i].x, h_pos.data[i].y, h_pos.data[i].z);
        const unsigned int type_i = __scalar_as_int(h_pos.data[i].w);
        const unsigned int body_i = h_body.data[i];
        const Scalar diam_i = h_diameter.data[i];

        const unsigned int Nmax_i = h_Nmax.data[type_i];
        const unsigned int head_idx_i = h_head_list.data[i];

        // find the bin each particle belongs in
        Scalar3 f = box.makeFraction(my_pos,ghost_width);
        int ib = (unsigned int)(f.x * dim.x);
        int jb = (unsigned int)(f.y * dim.y);
        int kb = (unsigned int)(f.z * dim.z);

        // need to handle the case where the particle is exactly at the box hi
        if (ib == (int)dim.x && periodic.x)
            ib = 0;
        if (jb == (int)dim.y && periodic.y)
            jb = 0;
        if (kb == (int)dim.z && periodic.z)
            kb = 0;

        // identify the bin
        unsigned int my_cell = ci(ib,jb,kb);

        // loop through all neighboring bins
        for (unsigned int cur_adj = 0; cur_adj < cadji.getW(); cur_adj++)
            {
            unsigned int neigh_cell = h_cell_adj.data[cadji(cur_adj, my_cell)];

            // check against all the particles in that neighboring bin to see if it is a neighbor
            unsigned int size = h_cell_size.data[neigh_cell];
            for (unsigned int cur_offset = 0; cur_offset < size; cur_offset++)
                {
                Scalar4& cur_xyzf = h_cell_xyzf.data[cli(cur_offset, neigh_cell)];
                unsigned int cur_neigh = __scalar_as_int(cur_xyzf.w);

                // get the current neighbor type from the position data (will use tdb on the GPU)
                unsigned int cur_neigh_type = __scalar_as_int(h_pos.data[cur_neigh].w);
                Scalar r_cut = h_r_cut.data[m_typpair_idx(type_i,cur_neigh_type)];

                // automatically exclude particles without a distance check when:
                // (1) they are the same particle, or
                // (2) the r_cut(i,j) indicates to skip, or
                // (3) they are in the same body
                bool excluded = ((i == (int)cur_neigh) || (r_cut <= Scalar(0.0)));
                if (m_filter_body && body_i != NO_BODY)
                    excluded = excluded | (body_i == h_body.data[cur_neigh]);
                if (excluded)
                    continue;

                Scalar3 neigh_pos = make_scalar3(cur_xyzf.x, cur_xyzf.y, cur_xyzf.z);
                Scalar3 dx = my_pos - neigh_pos;
                dx = box.minImage(dx);

                Scalar r_list = r_cut + m_r_buff;
                Scalar sqshift = Scalar(0.0);
                if (m_diameter_shift)
                    {
                    const Scalar delta = (diam_i + h_diameter.data[cur_neigh]) * Scalar(0.5) - Scalar(1.0);
                    // r^2 < (r_list + delta)^2
                    // r^2 < r_listsq + delta^2 + 2*r_list*delta
                    sqshift = (delta + Scalar(2.0) * r_list) * delta;
                    }

                Scalar dr_sq = dot(dx,dx);

                // move the squared rlist by the diameter shift if necessary
                Scalar r_listsq = h_r_listsq.data[m_typpair_idx(type_i,cur_neigh_type)];
                if (dr_sq <= (r_listsq + sqshift) && !excluded)
                    {
                    if (m_storage_mode == full || i < (int)cur_neigh)
                        {
                        // local neighbor
                        if (cur_n_neigh < Nmax_i)
                            {
                            h_nlist.data[head_idx_i + cur_n_neigh] = cur_neigh;
                            }
                        else
                            h_conditions.data[type_i] = max(h_conditions.data[type_i], cur_n_neigh+1);

                        cur_n_neigh++;
                        }
                    }
                }
            }

        h_n_neigh.data[i] = cur_n_neigh;
        }

    if (m_prof)
        m_prof->pop(m_exec_conf);
    }

void export_NeighborListBinned(py::module& m)
    {
    py::class_<NeighborListBinned, std::shared_ptr<NeighborListBinned> >(m, "NeighborListBinned", py::base<NeighborList>())
    .def(py::init< std::shared_ptr<SystemDefinition>, Scalar, Scalar, std::shared_ptr<CellList> >())
                     ;
    }
<|endoftext|>


<commit_before>/*   _____
 * /\  _  \                     __
 * \ \ \_\ \      __    __  __ /\_\
 *  \ \  __ \   /'_ `\ /\ \/\ \\/\ \
 *   \ \ \/\ \ /\ \_\ \\ \ \_\ \\ \ \
 *    \ \_\ \_\\ \____ \\ \____/ \ \_\
 *     \/_/\/_/ \/____\ \\/___/   \/_/
 *                /\____/
 *                \_/__/
 *
 * Copyright (c) 2011 Joshua Larouche
 *
 *
 * License: (BSD)
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 * 3. Neither the name of Agui 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 "Agui/Widgets/ToolTip/ToolTip.hpp"

namespace agui {

	ToolTip::ToolTip()
		: align(ALIGN_TOP_LEFT), invoker(NULL)
	{
		resizableText.setSingleLine(false);
		setVisibility(false);
		setFocusable(false);
		setTabable(false);
		setPreferredOffset(Point(10,10));
	}

	void ToolTip::mouseClick( MouseEvent &mouseEvent )
	{

		if(mouseEvent.getButton() == MOUSE_BUTTON_LEFT)
			dispatchActionEvent(ActionEvent(this));
	}

	void ToolTip::showToolTip( const std::string& text, int width, int x, int y, Widget* invoker )
	{
		this->invoker = invoker;

		setLocation(x,y);
		int w = width <= 0 ? 1000 : width;
		resizableText.makeTextLines(getFont(),text,wrappedText,w);

		int newHeight = wrappedText.size() * getFont()->getLineHeight();

		int newWidth = w;

			int widestLine = -1;
			for(size_t i = 0; i < wrappedText.size(); ++i)
			{
				int curWidth = getFont()->getTextWidth(wrappedText[i]);
				if(curWidth > widestLine)
				{
					widestLine = curWidth;
				}
			}

			if(widestLine < width)
			newWidth = widestLine;

		newWidth += (getMargin(SIDE_LEFT) + getMargin(SIDE_RIGHT));
		newHeight += (getMargin(SIDE_TOP) + getMargin(SIDE_BOTTOM));

		setSize(newWidth,newHeight);

		setVisibility(true);
	}

	const std::vector<std::string>& ToolTip::getAreaText() const
	{
		return wrappedText;
	}

	void ToolTip::paintBackground( const PaintEvent &paintEvent )
	{
		paintEvent.graphics()->drawFilledRectangle(
			getSizeRectangle(),getBackColor());
	}

	void ToolTip::paintComponent( const PaintEvent &paintEvent )
	{
		resizableText.drawTextArea(
			paintEvent.graphics(),getFont(),getInnerRectangle(),
			getFontColor(),getAreaText(),align);
	}

	void ToolTip::setTextAlignment( AreaAlignmentEnum alignment )
	{
		align = alignment;
	}

	agui::AreaAlignmentEnum ToolTip::getTextAlignment() const
	{
		return align;
	}

	void ToolTip::hideToolTip()
	{
		setVisibility(false);
		invoker = NULL;
	}

	void ToolTip::setPreferredOffset( Point offset )
	{
		preferredOffset = offset;
	}

	Point ToolTip::getPreferredOffset() const
	{
		return preferredOffset;
	}

	Widget* ToolTip::getInvoker() const
	{
		return invoker;
	}

}

<commit_msg>Added border around the tooltip widget, it looks better this way.<commit_after>/*   _____
 * /\  _  \                     __
 * \ \ \_\ \      __    __  __ /\_\
 *  \ \  __ \   /'_ `\ /\ \/\ \\/\ \
 *   \ \ \/\ \ /\ \_\ \\ \ \_\ \\ \ \
 *    \ \_\ \_\\ \____ \\ \____/ \ \_\
 *     \/_/\/_/ \/____\ \\/___/   \/_/
 *                /\____/
 *                \_/__/
 *
 * Copyright (c) 2011 Joshua Larouche
 *
 *
 * License: (BSD)
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 * 3. Neither the name of Agui 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 "Agui/Widgets/ToolTip/ToolTip.hpp"

namespace agui {

	ToolTip::ToolTip()
		: align(ALIGN_TOP_LEFT), invoker(NULL)
	{
		resizableText.setSingleLine(false);
		setVisibility(false);
		setFocusable(false);
		setTabable(false);
		setPreferredOffset(Point(10,10));
	}

	void ToolTip::mouseClick( MouseEvent &mouseEvent )
	{

		if(mouseEvent.getButton() == MOUSE_BUTTON_LEFT)
			dispatchActionEvent(ActionEvent(this));
	}

	void ToolTip::showToolTip( const std::string& text, int width, int x, int y, Widget* invoker )
	{
		this->invoker = invoker;

		setLocation(x,y);
		int w = width <= 0 ? 1000 : width;
		resizableText.makeTextLines(getFont(),text,wrappedText,w);

		int newHeight = wrappedText.size() * getFont()->getLineHeight();

		int newWidth = w;

			int widestLine = -1;
			for(size_t i = 0; i < wrappedText.size(); ++i)
			{
				int curWidth = getFont()->getTextWidth(wrappedText[i]);
				if(curWidth > widestLine)
				{
					widestLine = curWidth;
				}
			}

			if(widestLine < width)
			newWidth = widestLine;

		newWidth += (getMargin(SIDE_LEFT) + getMargin(SIDE_RIGHT));
		newHeight += (getMargin(SIDE_TOP) + getMargin(SIDE_BOTTOM));

		setSize(newWidth,newHeight);

		setVisibility(true);
	}

	const std::vector<std::string>& ToolTip::getAreaText() const
	{
		return wrappedText;
	}

	void ToolTip::paintBackground( const PaintEvent &paintEvent )
	{
		paintEvent.graphics()->drawFilledRectangle(
			getSizeRectangle(),getBackColor());
    paintEvent.graphics()->drawRectangle(getSizeRectangle(), getFontColor());
	}

	void ToolTip::paintComponent( const PaintEvent &paintEvent )
	{
		resizableText.drawTextArea(
			paintEvent.graphics(),getFont(),getInnerRectangle(),
			getFontColor(),getAreaText(),align);
	}

	void ToolTip::setTextAlignment( AreaAlignmentEnum alignment )
	{
		align = alignment;
	}

	agui::AreaAlignmentEnum ToolTip::getTextAlignment() const
	{
		return align;
	}

	void ToolTip::hideToolTip()
	{
		setVisibility(false);
		invoker = NULL;
	}

	void ToolTip::setPreferredOffset( Point offset )
	{
		preferredOffset = offset;
	}

	Point ToolTip::getPreferredOffset() const
	{
		return preferredOffset;
	}
	Widget* ToolTip::getInvoker() const
	{
		return invoker;
	}

}

<|endoftext|>


<commit_before>/*
 * Copyright (C) 2009 Marc Boris Duerner, Tommi Maekitalo
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * As a special exception, you may use this file as part of a free
 * software library without restriction. Specifically, if other files
 * instantiate templates or use macros or inline functions from this
 * file, or you compile this file and link it with other files to
 * produce an executable, this file does not by itself cause the
 * resulting executable to be covered by the GNU General Public
 * License. This exception does not however invalidate any other
 * reasons why the executable file might be covered by the GNU Library
 * General Public License.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "config.h"
#ifdef HAVE_ACCEPT4
#include <sys/types.h>
#include <sys/socket.h>
#endif

#include "tcpsocketimpl.h"
#include "tcpserverimpl.h"
#include "cxxtools/net/tcpserver.h"
#include "cxxtools/net/tcpsocket.h"
#include "cxxtools/systemerror.h"
#include "cxxtools/ioerror.h"
#include "cxxtools/log.h"
#include "config.h"
#include "error.h"
#include <cerrno>
#include <cstring>
#include <cassert>
#include <fcntl.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>

log_define("cxxtools.net.tcpsocket.impl")

namespace cxxtools
{

namespace net
{

void formatIp(const sockaddr_in& sa, std::string& str)
{
#ifdef HAVE_INET_NTOP
      char strbuf[INET6_ADDRSTRLEN + 1];
      const char* p = inet_ntop(sa.sin_family, &sa.sin_addr, strbuf, sizeof(strbuf));
      str = (p == 0 ? "-" : strbuf);
#else
      static cxxtools::Mutex monitor;
      cxxtools::MutexLock lock(monitor);

      const char* p = inet_ntoa(sa.sin_addr);
      if (p)
        str = p;
      else
        str.clear();
#endif
}

std::string getSockAddr(int fd)
{
    union
    {
      struct sockaddr_storage storage;
      struct sockaddr         sa;
      struct sockaddr_in      sa_in;
      struct sockaddr_in6     sa_in6;
      struct in_addr          addr;
    } addr;

    socklen_t slen = sizeof(addr);
    if (::getsockname(fd, &addr.sa, &slen) < 0)
        throw SystemError("getsockname");

    std::string ret;
    formatIp(addr.sa_in, ret);
    return ret;
}

TcpSocketImpl::TcpSocketImpl(TcpSocket& socket)
: IODeviceImpl(socket)
, _socket(socket)
, _isConnected(false)
{
}

TcpSocketImpl::~TcpSocketImpl()
{
    assert(_pfd == 0);
}

void TcpSocketImpl::close()
{
    log_debug("close socket " << _fd);
    IODeviceImpl::close();
    _isConnected = false;
}

std::string TcpSocketImpl::getSockAddr() const
{ return net::getSockAddr(fd()); }

std::string TcpSocketImpl::getPeerAddr() const
{
    union
    {
      struct sockaddr_storage storage;
      struct sockaddr         sa;
      struct sockaddr_in      sa_in;
      struct sockaddr_in6     sa_in6;
      struct in_addr          addr;
    } addr;

    addr.storage = _peeraddr;

    std::string ret;
    formatIp(addr.sa_in, ret);
    return ret;
}

void TcpSocketImpl::connect(const AddrInfo& addrInfo)
{
    log_debug("connect");
    this->beginConnect(addrInfo);
    this->endConnect();
}

int TcpSocketImpl::checkConnect()
{
    log_trace("checkConnect");

    int sockerr;
    socklen_t optlen = sizeof(sockerr);

    // check for socket error
    if( ::getsockopt(this->fd(), SOL_SOCKET, SO_ERROR, &sockerr, &optlen) != 0 )
    {
        // getsockopt failed
        int e = errno;
        close();
        throw SystemError(e, "getsockopt");
    }

    if (sockerr == 0)
    {
        log_debug("connected successfully to " << getPeerAddr());
        _isConnected = true;
    }

    return sockerr;
}

void TcpSocketImpl::checkPendingError()
{
    if (_connectResult.second)
    {
        std::pair<int, const char*> p = _connectResult;
        _connectResult = std::pair<int, const char*>(0, 0);

        if (p.first)
        {
            throw IOError(getErrnoString(p.first, p.second).c_str());
        }
        else
        {
            throw IOError("invalid address information");
        }
    }
}

std::pair<int, const char*> TcpSocketImpl::tryConnect()
{
    log_trace("tryConnect");

    assert(_fd == -1);

    if (_addrInfoPtr == _addrInfo.impl()->end())
    {
        log_debug("no more address informations");
        return std::pair<int, const char*>(0, "invalid address information");
    }

    while (true)
    {
        int fd;
        while (true)
        {
            log_debug("create socket");
            fd = ::socket(_addrInfoPtr->ai_family, SOCK_STREAM, 0);
            if (fd >= 0)
                break;

            if (++_addrInfoPtr == _addrInfo.impl()->end())
                return std::pair<int, const char*>(errno, "socket");
        }

        IODeviceImpl::open(fd, true, false);

        std::memmove(&_peeraddr, _addrInfoPtr->ai_addr, _addrInfoPtr->ai_addrlen);

        log_debug("created socket " << _fd << " max: " << FD_SETSIZE);

        if( ::connect(this->fd(), _addrInfoPtr->ai_addr, _addrInfoPtr->ai_addrlen) == 0 )
        {
            _isConnected = true;
            log_debug("connected successfully to " << getPeerAddr());
            break;
        }

        if (errno == EINPROGRESS)
        {
            log_debug("connect in progress");
            break;
        }

        close();
        if (++_addrInfoPtr == _addrInfo.impl()->end())
            return std::pair<int, const char*>(errno, "connect");
    }

    return std::pair<int, const char*>(0, 0);
}

bool TcpSocketImpl::beginConnect(const AddrInfo& addrInfo)
{
    log_trace("begin connect");

    assert(!_isConnected);

    _addrInfo = addrInfo;
    _addrInfoPtr = _addrInfo.impl()->begin();
    _connectResult = tryConnect();
    checkPendingError();
    return _isConnected;
}

void TcpSocketImpl::endConnect()
{
    log_trace("ending connect");

    if(_pfd && ! _socket.wbuf())
    {
        _pfd->events &= ~POLLOUT;
    }

    checkPendingError();

    if( _isConnected )
        return;

    try
    {
        while (true)
        {
            pollfd pfd;
            pfd.fd = this->fd();
            pfd.revents = 0;
            pfd.events = POLLOUT;

            log_debug("wait " << timeout() << " ms");
            bool avail = this->wait(this->timeout(), pfd);

            if (avail)
            {
                // something has happened
                int sockerr = checkConnect();
                if (_isConnected)
                    return;

                if (++_addrInfoPtr == _addrInfo.impl()->end())
                {
                    // no more addrInfo - propagate error
                    throw IOError(getErrnoString(sockerr, "connect").c_str());
                }
            }
            else if (++_addrInfoPtr == _addrInfo.impl()->end())
            {
                log_debug("timeout");
                throw IOTimeout();
            }

            close();

            _connectResult = tryConnect();
            if (_isConnected)
                return;
            checkPendingError();
        }
    }
    catch(...)
    {
        close();
        throw;
    }
}

void TcpSocketImpl::accept(const TcpServer& server, unsigned flags)
{
    socklen_t peeraddr_len = sizeof(_peeraddr);

    _fd = server.impl().accept(flags, reinterpret_cast <struct sockaddr*>(&_peeraddr), peeraddr_len);

    if( _fd < 0 )
        throw SystemError("accept");

#ifdef HAVE_ACCEPT4
    IODeviceImpl::open(_fd, false, false);
#else
    bool inherit = (flags & TcpSocket::INHERIT) != 0;
    IODeviceImpl::open(_fd, true, inherit);
#endif
    //TODO ECONNABORTED EINTR EPERM

    _isConnected = true;
    log_debug( "accepted from " << getPeerAddr());
}

void TcpSocketImpl::initWait(pollfd& pfd)
{
    IODeviceImpl::initWait(pfd);

    if( ! _isConnected )
    {
        log_debug("not connected, setting POLLOUT ");
        pfd.events = POLLOUT;
    }
}

bool TcpSocketImpl::checkPollEvent(pollfd& pfd)
{
    log_debug("checkPollEvent " << pfd.revents);

    if( _isConnected )
    {
        if ( pfd.revents & POLLERR )
        {
            _device.close();
            _socket.closed(_socket);
            return true;
        }

        return IODeviceImpl::checkPollEvent(pfd);
    }

    if ( pfd.revents & POLLERR )
    {
        AddrInfoImpl::const_iterator ptr = _addrInfoPtr;
        if (++ptr == _addrInfo.impl()->end())
        {
            // not really connected but error
            // end of addrinfo list means that no working addrinfo was found
            log_debug("no more addrinfos found");
            _socket.connected(_socket);
            return true;
        }
        else
        {
            _addrInfoPtr = ptr;

            close();
            _connectResult = tryConnect();

            if (_isConnected || _connectResult.second)
            {
                // immediate success or error
                log_debug("connected successfully");
                _socket.connected(_socket);
            }
            else
            {
                // by closing the previous file handle _pfd is set to 0.
                // creating a new socket in tryConnect may also change the value of fd.
                initializePoll(&pfd, 1);
            }

            return _isConnected;
        }
    }
    else if( pfd.revents & POLLOUT )
    {
        int sockerr = checkConnect();
        if (_isConnected)
        {
            _socket.connected(_socket);
            return true;
        }

        // something went wrong - look for next addrInfo
        log_debug("sockerr is " << sockerr << " try next");
        if (++_addrInfoPtr == _addrInfo.impl()->end())
        {
            // no more addrInfo - propagate error
            _connectResult = std::pair<int, const char*>(sockerr, "connect");
            _socket.connected(_socket);
            return true;
        }

        _connectResult = tryConnect();
        if (_isConnected)
        {
            _socket.connected(_socket);
            return true;
        }
    }

    return false;
}

} // namespace net

} // namespace cxxtools
<commit_msg>fix handling of closed sockets<commit_after>/*
 * Copyright (C) 2009 Marc Boris Duerner, Tommi Maekitalo
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * As a special exception, you may use this file as part of a free
 * software library without restriction. Specifically, if other files
 * instantiate templates or use macros or inline functions from this
 * file, or you compile this file and link it with other files to
 * produce an executable, this file does not by itself cause the
 * resulting executable to be covered by the GNU General Public
 * License. This exception does not however invalidate any other
 * reasons why the executable file might be covered by the GNU Library
 * General Public License.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "config.h"
#ifdef HAVE_ACCEPT4
#include <sys/types.h>
#include <sys/socket.h>
#endif

#include "tcpsocketimpl.h"
#include "tcpserverimpl.h"
#include "cxxtools/net/tcpserver.h"
#include "cxxtools/net/tcpsocket.h"
#include "cxxtools/systemerror.h"
#include "cxxtools/ioerror.h"
#include "cxxtools/log.h"
#include "config.h"
#include "error.h"
#include <cerrno>
#include <cstring>
#include <cassert>
#include <fcntl.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>

log_define("cxxtools.net.tcpsocket.impl")

namespace cxxtools
{

namespace net
{

void formatIp(const sockaddr_in& sa, std::string& str)
{
#ifdef HAVE_INET_NTOP
      char strbuf[INET6_ADDRSTRLEN + 1];
      const char* p = inet_ntop(sa.sin_family, &sa.sin_addr, strbuf, sizeof(strbuf));
      str = (p == 0 ? "-" : strbuf);
#else
      static cxxtools::Mutex monitor;
      cxxtools::MutexLock lock(monitor);

      const char* p = inet_ntoa(sa.sin_addr);
      if (p)
        str = p;
      else
        str.clear();
#endif
}

std::string getSockAddr(int fd)
{
    union
    {
      struct sockaddr_storage storage;
      struct sockaddr         sa;
      struct sockaddr_in      sa_in;
      struct sockaddr_in6     sa_in6;
      struct in_addr          addr;
    } addr;

    socklen_t slen = sizeof(addr);
    if (::getsockname(fd, &addr.sa, &slen) < 0)
        throw SystemError("getsockname");

    std::string ret;
    formatIp(addr.sa_in, ret);
    return ret;
}

TcpSocketImpl::TcpSocketImpl(TcpSocket& socket)
: IODeviceImpl(socket)
, _socket(socket)
, _isConnected(false)
{
}

TcpSocketImpl::~TcpSocketImpl()
{
    assert(_pfd == 0);
}

void TcpSocketImpl::close()
{
    log_debug("close socket " << _fd);
    IODeviceImpl::close();
    _isConnected = false;
}

std::string TcpSocketImpl::getSockAddr() const
{ return net::getSockAddr(fd()); }

std::string TcpSocketImpl::getPeerAddr() const
{
    union
    {
      struct sockaddr_storage storage;
      struct sockaddr         sa;
      struct sockaddr_in      sa_in;
      struct sockaddr_in6     sa_in6;
      struct in_addr          addr;
    } addr;

    addr.storage = _peeraddr;

    std::string ret;
    formatIp(addr.sa_in, ret);
    return ret;
}

void TcpSocketImpl::connect(const AddrInfo& addrInfo)
{
    log_debug("connect");
    this->beginConnect(addrInfo);
    this->endConnect();
}

int TcpSocketImpl::checkConnect()
{
    log_trace("checkConnect");

    int sockerr;
    socklen_t optlen = sizeof(sockerr);

    // check for socket error
    if( ::getsockopt(this->fd(), SOL_SOCKET, SO_ERROR, &sockerr, &optlen) != 0 )
    {
        // getsockopt failed
        int e = errno;
        close();
        throw SystemError(e, "getsockopt");
    }

    if (sockerr == 0)
    {
        log_debug("connected successfully to " << getPeerAddr());
        _isConnected = true;
    }

    return sockerr;
}

void TcpSocketImpl::checkPendingError()
{
    if (_connectResult.second)
    {
        std::pair<int, const char*> p = _connectResult;
        _connectResult = std::pair<int, const char*>(0, 0);

        if (p.first)
        {
            throw IOError(getErrnoString(p.first, p.second).c_str());
        }
        else
        {
            throw IOError("invalid address information");
        }
    }
}

std::pair<int, const char*> TcpSocketImpl::tryConnect()
{
    log_trace("tryConnect");

    assert(_fd == -1);

    if (_addrInfoPtr == _addrInfo.impl()->end())
    {
        log_debug("no more address informations");
        return std::pair<int, const char*>(0, "invalid address information");
    }

    while (true)
    {
        int fd;
        while (true)
        {
            log_debug("create socket");
            fd = ::socket(_addrInfoPtr->ai_family, SOCK_STREAM, 0);
            if (fd >= 0)
                break;

            if (++_addrInfoPtr == _addrInfo.impl()->end())
                return std::pair<int, const char*>(errno, "socket");
        }

        IODeviceImpl::open(fd, true, false);

        std::memmove(&_peeraddr, _addrInfoPtr->ai_addr, _addrInfoPtr->ai_addrlen);

        log_debug("created socket " << _fd << " max: " << FD_SETSIZE);

        if( ::connect(this->fd(), _addrInfoPtr->ai_addr, _addrInfoPtr->ai_addrlen) == 0 )
        {
            _isConnected = true;
            log_debug("connected successfully to " << getPeerAddr());
            break;
        }

        if (errno == EINPROGRESS)
        {
            log_debug("connect in progress");
            break;
        }

        close();
        if (++_addrInfoPtr == _addrInfo.impl()->end())
            return std::pair<int, const char*>(errno, "connect");
    }

    return std::pair<int, const char*>(0, 0);
}

bool TcpSocketImpl::beginConnect(const AddrInfo& addrInfo)
{
    log_trace("begin connect");

    assert(!_isConnected);

    _addrInfo = addrInfo;
    _addrInfoPtr = _addrInfo.impl()->begin();
    _connectResult = tryConnect();
    checkPendingError();
    return _isConnected;
}

void TcpSocketImpl::endConnect()
{
    log_trace("ending connect");

    if(_pfd && ! _socket.wbuf())
    {
        _pfd->events &= ~POLLOUT;
    }

    checkPendingError();

    if( _isConnected )
        return;

    try
    {
        while (true)
        {
            pollfd pfd;
            pfd.fd = this->fd();
            pfd.revents = 0;
            pfd.events = POLLOUT;

            log_debug("wait " << timeout() << " ms");
            bool avail = this->wait(this->timeout(), pfd);

            if (avail)
            {
                // something has happened
                int sockerr = checkConnect();
                if (_isConnected)
                    return;

                if (++_addrInfoPtr == _addrInfo.impl()->end())
                {
                    // no more addrInfo - propagate error
                    throw IOError(getErrnoString(sockerr, "connect").c_str());
                }
            }
            else if (++_addrInfoPtr == _addrInfo.impl()->end())
            {
                log_debug("timeout");
                throw IOTimeout();
            }

            close();

            _connectResult = tryConnect();
            if (_isConnected)
                return;
            checkPendingError();
        }
    }
    catch(...)
    {
        close();
        throw;
    }
}

void TcpSocketImpl::accept(const TcpServer& server, unsigned flags)
{
    socklen_t peeraddr_len = sizeof(_peeraddr);

    _fd = server.impl().accept(flags, reinterpret_cast <struct sockaddr*>(&_peeraddr), peeraddr_len);

    if( _fd < 0 )
        throw SystemError("accept");

#ifdef HAVE_ACCEPT4
    IODeviceImpl::open(_fd, false, false);
#else
    bool inherit = (flags & TcpSocket::INHERIT) != 0;
    IODeviceImpl::open(_fd, true, inherit);
#endif
    //TODO ECONNABORTED EINTR EPERM

    _isConnected = true;
    log_debug( "accepted from " << getPeerAddr());
}

void TcpSocketImpl::initWait(pollfd& pfd)
{
    IODeviceImpl::initWait(pfd);

    if( ! _isConnected )
    {
        log_debug("not connected, setting POLLOUT ");
        pfd.events = POLLOUT;
    }
}

bool TcpSocketImpl::checkPollEvent(pollfd& pfd)
{
    log_debug("checkPollEvent " << pfd.revents);

    if( _isConnected )
    {
        // check for error while neither reading nor writing
        //
        // if reading or writing, IODeviceImpl::checkPollEvent will emit
        // inputReady or outputReady signal and the user gets an exception in
        // endRead or endWrite.
        if ( !_device.reading() && !_device.writing()
            && (pfd.revents & POLLERR) )
        {
            _device.close();
            _socket.closed(_socket);
            return true;
        }

        return IODeviceImpl::checkPollEvent(pfd);
    }

    if ( pfd.revents & POLLERR )
    {
        AddrInfoImpl::const_iterator ptr = _addrInfoPtr;
        if (++ptr == _addrInfo.impl()->end())
        {
            // not really connected but error
            // end of addrinfo list means that no working addrinfo was found
            log_debug("no more addrinfos found");
            _socket.connected(_socket);
            return true;
        }
        else
        {
            _addrInfoPtr = ptr;

            close();
            _connectResult = tryConnect();

            if (_isConnected || _connectResult.second)
            {
                // immediate success or error
                log_debug("connected successfully");
                _socket.connected(_socket);
            }
            else
            {
                // by closing the previous file handle _pfd is set to 0.
                // creating a new socket in tryConnect may also change the value of fd.
                initializePoll(&pfd, 1);
            }

            return _isConnected;
        }
    }
    else if( pfd.revents & POLLOUT )
    {
        int sockerr = checkConnect();
        if (_isConnected)
        {
            _socket.connected(_socket);
            return true;
        }

        // something went wrong - look for next addrInfo
        log_debug("sockerr is " << sockerr << " try next");
        if (++_addrInfoPtr == _addrInfo.impl()->end())
        {
            // no more addrInfo - propagate error
            _connectResult = std::pair<int, const char*>(sockerr, "connect");
            _socket.connected(_socket);
            return true;
        }

        _connectResult = tryConnect();
        if (_isConnected)
        {
            _socket.connected(_socket);
            return true;
        }
    }

    return false;
}

} // namespace net

} // namespace cxxtools
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2008-2009
 *
 * School of Computing, University of Utah,
 * Salt Lake City, UT 84112, USA
 *
 * and the Gauss Group
 * http://www.cs.utah.edu/formal_verification
 *
 * See LICENSE for licensing information
 */

/*
 * ISP: MPI Dynamic Verification Tool
 *
 * File:        TransitionList.hpp
 * Description: Implements lists of transitions from an interleaving
 * Contact:     isp-dev@cs.utah.edu
 */

#ifndef _TRANSITIONLIST_HPP
#define _TRANSITIONLIST_HPP

#include <vector>
#include <list>
#include <algorithm>
#include <sstream>
#include <memory>
#include <boost/iterator/indirect_iterator.hpp>

#include "Envelope.hpp"
#include "Transition.hpp"

using std::unique_ptr;
using std::vector;
using boost::indirect_iterator;
using boost::make_indirect_iterator;

/*
 * This implements a TransitionList and updates "Intra-Completes-Before"
 */
class TransitionList {

public:
    inline int getId() const { return id; }
    inline unsigned int size() const { return tlist.size(); }
    inline const Transition & get(int index) const {
        return *tlist[index];
    }
    bool addTransition (unique_ptr<Transition> t);

    inline indirect_iterator<vector<unique_ptr<Transition> >::iterator> begin () {
        return make_indirect_iterator(tlist.begin());
    }

    inline indirect_iterator<vector<unique_ptr<Transition> >::iterator> end () {
        return make_indirect_iterator(tlist.end());
    }

    inline indirect_iterator<vector<unique_ptr<Transition> >::reverse_iterator> rbegin () {
        return make_indirect_iterator(tlist.rbegin());
    }

    inline indirect_iterator<vector<unique_ptr<Transition> >::reverse_iterator> rend () {
        return make_indirect_iterator(tlist.rend());
    }

private:
    std::vector<std::unique_ptr<Transition> > tlist;
    std::list<int> ulist;
    int id;
    inline bool intraCB (const Transition &f, const Transition &s) const {
        const auto &env_f = f.getEnvelope();
        const auto &env_s = s.getEnvelope();

        /*
         * Find Intra-Completes-Before :
         * 1) Blocking rule
         */
        if (env_f.isBlockingType ()) {
            return true;
        }

        /*
         * 2) Send order rule
         */

        if (env_f.isSendType () &&
            env_s.isSendType () &&
            env_f.dest == env_s.dest &&
            env_f.comm == env_s.comm &&
            env_f.stag == env_s.stag) {
            return true;
        }
        /*
         * 3) Recv order rule
         */
        if (env_f.isRecvType () &&
            env_s.isRecvType () &&
            (env_f.src == env_s.src ||
             env_f.src == WILDCARD) &&
            env_f.comm == env_s.comm &&
            (env_f.rtag == env_s.rtag ||
             env_f.rtag == WILDCARD)) {
            return true;
        }

        /*
         * 4) iRecv -> Wait order rule
         */
        if (env_f.func_id == IRECV &&
                ((env_s.func_id == WAIT) ||
                 (env_s.func_id == TEST)) &&
                env_f.count == env_s.count) {
            return true;
        }

        if (env_f.func_id == ISEND &&
                ((env_s.func_id == WAIT) ||
                 (env_s.func_id == TEST)) &&
                env_f.count == env_s.count) {
            return true;
        }

        if (((env_s.func_id == WAITALL) ||
                (env_s.func_id == WAITANY) ||
                (env_s.func_id == TESTANY) ||
                (env_s.func_id == TESTALL) ) &&
                (env_f.func_id == IRECV ||
                 env_f.func_id == ISEND)) {

            for (int i = 0 ; i < env_s.count ; i++) {
                if (env_s.req_procs[i] == env_f.index) {
                    return true;
                }
            }
        }

        if (env_s.func_id == FINALIZE) {
            return true;
        }

        return false;
    }

};

#endif
<commit_msg>Removed const as it is too strong.<commit_after>/*
 * Copyright (c) 2008-2009
 *
 * School of Computing, University of Utah,
 * Salt Lake City, UT 84112, USA
 *
 * and the Gauss Group
 * http://www.cs.utah.edu/formal_verification
 *
 * See LICENSE for licensing information
 */

/*
 * ISP: MPI Dynamic Verification Tool
 *
 * File:        TransitionList.hpp
 * Description: Implements lists of transitions from an interleaving
 * Contact:     isp-dev@cs.utah.edu
 */

#ifndef _TRANSITIONLIST_HPP
#define _TRANSITIONLIST_HPP

#include <vector>
#include <list>
#include <algorithm>
#include <sstream>
#include <memory>
#include <boost/iterator/indirect_iterator.hpp>

#include "Envelope.hpp"
#include "Transition.hpp"

using std::unique_ptr;
using std::vector;
using boost::indirect_iterator;
using boost::make_indirect_iterator;

/*
 * This implements a TransitionList and updates "Intra-Completes-Before"
 */
class TransitionList {

public:
    inline int getId() const { return id; }
    inline unsigned int size() const { return tlist.size(); }
    inline Transition & get(int index) const { return *tlist[index]; }
    bool addTransition (unique_ptr<Transition> t);

    inline indirect_iterator<vector<unique_ptr<Transition> >::iterator> begin () {
        return make_indirect_iterator(tlist.begin());
    }

    inline indirect_iterator<vector<unique_ptr<Transition> >::iterator> end () {
        return make_indirect_iterator(tlist.end());
    }

    inline indirect_iterator<vector<unique_ptr<Transition> >::reverse_iterator> rbegin () {
        return make_indirect_iterator(tlist.rbegin());
    }

    inline indirect_iterator<vector<unique_ptr<Transition> >::reverse_iterator> rend () {
        return make_indirect_iterator(tlist.rend());
    }

private:
    std::vector<std::unique_ptr<Transition> > tlist;
    std::list<int> ulist;
    int id;
    inline bool intraCB (const Transition &f, const Transition &s) const {
        const auto &env_f = f.getEnvelope();
        const auto &env_s = s.getEnvelope();

        /*
         * Find Intra-Completes-Before :
         * 1) Blocking rule
         */
        if (env_f.isBlockingType ()) {
            return true;
        }

        /*
         * 2) Send order rule
         */

        if (env_f.isSendType () &&
            env_s.isSendType () &&
            env_f.dest == env_s.dest &&
            env_f.comm == env_s.comm &&
            env_f.stag == env_s.stag) {
            return true;
        }
        /*
         * 3) Recv order rule
         */
        if (env_f.isRecvType () &&
            env_s.isRecvType () &&
            (env_f.src == env_s.src ||
             env_f.src == WILDCARD) &&
            env_f.comm == env_s.comm &&
            (env_f.rtag == env_s.rtag ||
             env_f.rtag == WILDCARD)) {
            return true;
        }

        /*
         * 4) iRecv -> Wait order rule
         */
        if (env_f.func_id == IRECV &&
                ((env_s.func_id == WAIT) ||
                 (env_s.func_id == TEST)) &&
                env_f.count == env_s.count) {
            return true;
        }

        if (env_f.func_id == ISEND &&
                ((env_s.func_id == WAIT) ||
                 (env_s.func_id == TEST)) &&
                env_f.count == env_s.count) {
            return true;
        }

        if (((env_s.func_id == WAITALL) ||
                (env_s.func_id == WAITANY) ||
                (env_s.func_id == TESTANY) ||
                (env_s.func_id == TESTALL) ) &&
                (env_f.func_id == IRECV ||
                 env_f.func_id == ISEND)) {

            for (int i = 0 ; i < env_s.count ; i++) {
                if (env_s.req_procs[i] == env_f.index) {
                    return true;
                }
            }
        }

        if (env_s.func_id == FINALIZE) {
            return true;
        }

        return false;
    }

};

#endif
<|endoftext|>