<commit_before>//===----------------------------------------------------------------------===//
//
//                         PelotonDB
//
// mvcc_test.cpp
//
// Identification: tests/concurrency/mvcc_test.cpp
//
// Copyright (c) 2015-16, Carnegie Mellon University Database Group
//
//===----------------------------------------------------------------------===//

#include "harness.h"
#include "concurrency/transaction_tests_util.h"

namespace peloton {

namespace test {

//===--------------------------------------------------------------------===//
// Transaction Tests
//===--------------------------------------------------------------------===//

class MVCCTest : public PelotonTest {};

// Validate that MVCC storage is correct, it assumes an old-to-new chain
// Invariants
// 1. Transaction id should either be INVALID_TXNID or INITIAL_TXNID
// 2. Begin commit id should <= end commit id
// 3. Timestamp consistence
// 4. Version doubly linked list consistency
static void ValidateMVCC_OldToNew(storage::DataTable *table) {
  auto &gc_manager = gc::GCManagerFactory::GetInstance();
  auto &catalog_manager = catalog::Manager::GetInstance();
  gc_manager.StopGC();
  LOG_INFO("Validating MVCC storage");
  int tile_group_count = table->GetTileGroupCount();
  LOG_INFO("The table has %d tile groups in the table", tile_group_count);

  for (int tile_group_offset = 0; tile_group_offset < tile_group_count; tile_group_offset++) {
    LOG_INFO("Validate tile group #%d", tile_group_offset);
    auto tile_group = table->GetTileGroup(tile_group_offset);
    auto tile_group_header = tile_group->GetHeader();
    size_t tuple_count = tile_group->GetAllocatedTupleCount();
    LOG_INFO("Tile group #%d has allocated %lu tuples", tile_group_offset, tuple_count);

    // 1. Transaction id should either be INVALID_TXNID or INITIAL_TXNID
    for (oid_t tuple_slot = 0; tuple_slot < tuple_count; tuple_slot++) {
      txn_id_t txn_id = tile_group_header->GetTransactionId(tuple_slot);
      EXPECT_TRUE(txn_id == INVALID_TXN_ID || txn_id == INITIAL_TXN_ID) << "Transaction id is not INVALID_TXNID or INITIAL_TXNID";
    }

    LOG_INFO("[OK] All tuples have valid txn id");

    // double avg_version_chain_length = 0.0;
    for (oid_t tuple_slot = 0; tuple_slot < tuple_count; tuple_slot++) {
      txn_id_t txn_id = tile_group_header->GetTransactionId(tuple_slot);
      cid_t begin_cid = tile_group_header->GetBeginCommitId(tuple_slot);
      cid_t end_cid = tile_group_header->GetEndCommitId(tuple_slot);
      ItemPointer next_location = tile_group_header->GetNextItemPointer(tuple_slot);
      ItemPointer prev_location = tile_group_header->GetPrevItemPointer(tuple_slot);

      // 2. Begin commit id should <= end commit id
      EXPECT_TRUE(begin_cid <= end_cid) << "Tuple begin commit id is less than or equal to end commit id";

      // This test assumes a oldest-to-newest version chain
      if (txn_id != INVALID_TXN_ID) {
        EXPECT_TRUE(begin_cid != MAX_CID) << "Non invalid txn shouldn't have a MAX_CID begin commit id";

        // The version is an oldest version
        if (prev_location.IsNull()) {
          if (next_location.IsNull()) {
            EXPECT_EQ(end_cid, MAX_CID) << "Single version has a non MAX_CID end commit time";
          } else {
            cid_t prev_end_cid = end_cid;
            ItemPointer prev_location(tile_group_offset, tuple_slot);
            while (!next_location.IsNull()) {
              auto next_tile_group = catalog_manager.GetTileGroup(next_location.block);
              auto next_tile_group_header = next_tile_group->GetHeader();

              txn_id_t next_txn_id = next_tile_group_header->GetTransactionId(next_location.offset);

              if (next_txn_id == INVALID_TXN_ID) {
                // If a version in the version chain has a INVALID_TXN_ID, it must be at the tail
                // of the chain. It is either because we have deleted a tuple (so append a invalid tuple),
                // or because this new version is aborted.
                EXPECT_TRUE(next_tile_group_header->GetNextItemPointer(next_location.offset).IsNull()) << "Invalid version in a version chain and is not delete";
              }

              cid_t next_begin_cid = next_tile_group_header->GetBeginCommitId(next_location.offset);
              cid_t next_end_cid = next_tile_group_header->GetEndCommitId(next_location.offset);

              // 3. Timestamp consistence
              if (next_begin_cid == MAX_CID) {
                // It must be an aborted version, it should be at the end of the chain
                EXPECT_TRUE(next_tile_group_header->GetNextItemPointer(next_location.offset).IsNull()) << "Version with MAX_CID begin cid is not version tail";
              } else {
                EXPECT_EQ(prev_end_cid, next_begin_cid) << "Prev end commit id should equal net begin commit id";
                ItemPointer next_prev_location = next_tile_group_header->GetPrevItemPointer(next_location.offset);

                // 4. Version doubly linked list consistency
                EXPECT_TRUE(next_prev_location.offset == prev_location.offset &&
                        next_prev_location.block == prev_location.block) << "Next version's prev version does not match";
              }

              prev_location = next_location;
              prev_end_cid = next_end_cid;
              next_location = next_tile_group_header->GetNextItemPointer(next_location.offset);
            }

            // Now prev_location is at the tail of the version chain
            ItemPointer last_location = prev_location;
            auto last_tile_group = catalog_manager.GetTileGroup(last_location.block);
            auto last_tile_group_header = last_tile_group->GetHeader();
            // txn_id_t last_txn_id = last_tile_group_header->GetTransactionId(last_location.offset);
            cid_t last_end_cid = last_tile_group_header->GetEndCommitId(last_location.offset);
            EXPECT_TRUE(last_tile_group_header->GetNextItemPointer(last_location.offset).IsNull()) << "Last version has a next pointer";

            EXPECT_EQ(last_end_cid , MAX_CID) << "Last version doesn't end with MAX_CID";
          }
        }
      } else {
        EXPECT_TRUE(tile_group_header->GetNextItemPointer(tuple_slot).IsNull()) << "Invalid tuple must not have next item pointer";
      }
    }
    LOG_INFO("[OK] oldest-to-newest version chain validated");
  }

  gc_manager.StartGC();
}

TEST_F(MVCCTest, SingleThreadVersionChainTest) {
  auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance();
  std::unique_ptr<storage::DataTable> table(
      TransactionTestsUtil::CreateTable());
  // read, read, read, read, update, read, read not exist
  // another txn read
  {
    TransactionScheduler scheduler(2, table.get(), &txn_manager);
    scheduler.Txn(0).Read(0);
    scheduler.Txn(0).Read(0);
    scheduler.Txn(0).Read(0);
    scheduler.Txn(0).Read(0);
    scheduler.Txn(0).Update(0, 1);
    scheduler.Txn(0).Read(0);
    scheduler.Txn(0).Read(100);
    scheduler.Txn(0).Commit();
    scheduler.Txn(1).Read(0);
    scheduler.Txn(1).Commit();

    scheduler.Run();

    ValidateMVCC_OldToNew(table.get());
  }

  // update, update, update, update, read
  {
    TransactionScheduler scheduler(1, table.get(), &txn_manager);
    scheduler.Txn(0).Update(0, 1);
    scheduler.Txn(0).Update(0, 2);
    scheduler.Txn(0).Update(0, 3);
    scheduler.Txn(0).Update(0, 4);
    scheduler.Txn(0).Read(0);
    scheduler.Txn(0).Commit();

    scheduler.Run();

    ValidateMVCC_OldToNew(table.get());
  }

  // delete not exist, delete exist, read deleted, update deleted,
  // read deleted, insert back, update inserted, read newly updated,
  // delete inserted, read deleted
  {
    TransactionScheduler scheduler(1, table.get(), &txn_manager);
    scheduler.Txn(0).Delete(100);
    scheduler.Txn(0).Delete(0);
    scheduler.Txn(0).Read(0);
    scheduler.Txn(0).Update(0, 1);
    scheduler.Txn(0).Read(0);
    scheduler.Txn(0).Insert(0, 2);
    scheduler.Txn(0).Update(0, 3);
    scheduler.Txn(0).Read(0);
    scheduler.Txn(0).Delete(0);
    scheduler.Txn(0).Read(0);
    scheduler.Txn(0).Commit();

    scheduler.Run();

    ValidateMVCC_OldToNew(table.get());
  }

  // insert, delete inserted, read deleted, insert again, delete again
  // read deleted, insert again, read inserted, update inserted, read updated
  {
    TransactionScheduler scheduler(1, table.get(), &txn_manager);

    scheduler.Txn(0).Insert(1000, 0);
    scheduler.Txn(0).Delete(1000);
    scheduler.Txn(0).Read(1000);
    scheduler.Txn(0).Insert(1000, 1);
    scheduler.Txn(0).Delete(1000);
    scheduler.Txn(0).Read(1000);
    scheduler.Txn(0).Insert(1000, 2);
    scheduler.Txn(0).Read(1000);
    scheduler.Txn(0).Update(1000, 3);
    scheduler.Txn(0).Read(1000);
    scheduler.Txn(0).Commit();

    scheduler.Run();

    ValidateMVCC_OldToNew(table.get());
  }
}

TEST_F(MVCCTest, VersionChainTest) {
  const int num_txn = 5;
  const int scale = 20;
  const int num_key = 256;
  srand(15721);

  std::unique_ptr<storage::DataTable> table(
      TransactionTestsUtil::CreateTable(num_key));
  auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance();

  TransactionScheduler scheduler(num_txn, table.get(), &txn_manager);
  scheduler.SetConcurrent(true);
  for (int i = 0; i < num_txn; i++) {
    for (int j = 0; j < scale; j++) {
      // randomly select two uniq keys
      int key1 = rand() % num_key;
      int key2 = rand() % num_key;
      int delta = rand() % 1000;
      // Store substracted value
      scheduler.Txn(i).ReadStore(key1, -delta);
      scheduler.Txn(i).Update(key1, TXN_STORED_VALUE);
      // Store increased value
      scheduler.Txn(i).ReadStore(key2, delta);
      scheduler.Txn(i).Update(key2, TXN_STORED_VALUE);
    }
    scheduler.Txn(i).Commit();
  }
  scheduler.Run();

  // Read all values
  TransactionScheduler scheduler2(1, table.get(), &txn_manager);
  for (int i = 0; i < num_key; i++) {
    scheduler2.Txn(0).Read(i);
  }
  scheduler2.Txn(0).Commit();
  scheduler2.Run();

  ValidateMVCC_OldToNew(table.get());
}

}  // End test namespace
}  // End peloton namespace
<commit_msg>add abort version chain test<commit_after>//===----------------------------------------------------------------------===//
//
//                         PelotonDB
//
// mvcc_test.cpp
//
// Identification: tests/concurrency/mvcc_test.cpp
//
// Copyright (c) 2015-16, Carnegie Mellon University Database Group
//
//===----------------------------------------------------------------------===//

#include "harness.h"
#include "concurrency/transaction_tests_util.h"

namespace peloton {

namespace test {

//===--------------------------------------------------------------------===//
// Transaction Tests
//===--------------------------------------------------------------------===//

class MVCCTest : public PelotonTest {};

// Validate that MVCC storage is correct, it assumes an old-to-new chain
// Invariants
// 1. Transaction id should either be INVALID_TXNID or INITIAL_TXNID
// 2. Begin commit id should <= end commit id
// 3. Timestamp consistence
// 4. Version doubly linked list consistency
static void ValidateMVCC_OldToNew(storage::DataTable *table) {
  auto &gc_manager = gc::GCManagerFactory::GetInstance();
  auto &catalog_manager = catalog::Manager::GetInstance();
  gc_manager.StopGC();
  LOG_INFO("Validating MVCC storage");
  int tile_group_count = table->GetTileGroupCount();
  LOG_INFO("The table has %d tile groups in the table", tile_group_count);

  for (int tile_group_offset = 0; tile_group_offset < tile_group_count; tile_group_offset++) {
    LOG_INFO("Validate tile group #%d", tile_group_offset);
    auto tile_group = table->GetTileGroup(tile_group_offset);
    auto tile_group_header = tile_group->GetHeader();
    size_t tuple_count = tile_group->GetAllocatedTupleCount();
    LOG_INFO("Tile group #%d has allocated %lu tuples", tile_group_offset, tuple_count);

    // 1. Transaction id should either be INVALID_TXNID or INITIAL_TXNID
    for (oid_t tuple_slot = 0; tuple_slot < tuple_count; tuple_slot++) {
      txn_id_t txn_id = tile_group_header->GetTransactionId(tuple_slot);
      EXPECT_TRUE(txn_id == INVALID_TXN_ID || txn_id == INITIAL_TXN_ID) << "Transaction id is not INVALID_TXNID or INITIAL_TXNID";
    }

    LOG_INFO("[OK] All tuples have valid txn id");

    // double avg_version_chain_length = 0.0;
    for (oid_t tuple_slot = 0; tuple_slot < tuple_count; tuple_slot++) {
      txn_id_t txn_id = tile_group_header->GetTransactionId(tuple_slot);
      cid_t begin_cid = tile_group_header->GetBeginCommitId(tuple_slot);
      cid_t end_cid = tile_group_header->GetEndCommitId(tuple_slot);
      ItemPointer next_location = tile_group_header->GetNextItemPointer(tuple_slot);
      ItemPointer prev_location = tile_group_header->GetPrevItemPointer(tuple_slot);

      // 2. Begin commit id should <= end commit id
      EXPECT_TRUE(begin_cid <= end_cid) << "Tuple begin commit id is less than or equal to end commit id";

      // This test assumes a oldest-to-newest version chain
      if (txn_id != INVALID_TXN_ID) {
        EXPECT_TRUE(begin_cid != MAX_CID) << "Non invalid txn shouldn't have a MAX_CID begin commit id";

        // The version is an oldest version
        if (prev_location.IsNull()) {
          if (next_location.IsNull()) {
            EXPECT_EQ(end_cid, MAX_CID) << "Single version has a non MAX_CID end commit time";
          } else {
            cid_t prev_end_cid = end_cid;
            ItemPointer prev_location(tile_group_offset, tuple_slot);
            while (!next_location.IsNull()) {
              auto next_tile_group = catalog_manager.GetTileGroup(next_location.block);
              auto next_tile_group_header = next_tile_group->GetHeader();

              txn_id_t next_txn_id = next_tile_group_header->GetTransactionId(next_location.offset);

              if (next_txn_id == INVALID_TXN_ID) {
                // If a version in the version chain has a INVALID_TXN_ID, it must be at the tail
                // of the chain. It is either because we have deleted a tuple (so append a invalid tuple),
                // or because this new version is aborted.
                EXPECT_TRUE(next_tile_group_header->GetNextItemPointer(next_location.offset).IsNull()) << "Invalid version in a version chain and is not delete";
              }

              cid_t next_begin_cid = next_tile_group_header->GetBeginCommitId(next_location.offset);
              cid_t next_end_cid = next_tile_group_header->GetEndCommitId(next_location.offset);

              // 3. Timestamp consistence
              if (next_begin_cid == MAX_CID) {
                // It must be an aborted version, it should be at the end of the chain
                EXPECT_TRUE(next_tile_group_header->GetNextItemPointer(next_location.offset).IsNull()) << "Version with MAX_CID begin cid is not version tail";
              } else {
                EXPECT_EQ(prev_end_cid, next_begin_cid) << "Prev end commit id should equal net begin commit id";
                ItemPointer next_prev_location = next_tile_group_header->GetPrevItemPointer(next_location.offset);

                // 4. Version doubly linked list consistency
                EXPECT_TRUE(next_prev_location.offset == prev_location.offset &&
                        next_prev_location.block == prev_location.block) << "Next version's prev version does not match";
              }

              prev_location = next_location;
              prev_end_cid = next_end_cid;
              next_location = next_tile_group_header->GetNextItemPointer(next_location.offset);
            }

            // Now prev_location is at the tail of the version chain
            ItemPointer last_location = prev_location;
            auto last_tile_group = catalog_manager.GetTileGroup(last_location.block);
            auto last_tile_group_header = last_tile_group->GetHeader();
            // txn_id_t last_txn_id = last_tile_group_header->GetTransactionId(last_location.offset);
            cid_t last_end_cid = last_tile_group_header->GetEndCommitId(last_location.offset);
            EXPECT_TRUE(last_tile_group_header->GetNextItemPointer(last_location.offset).IsNull()) << "Last version has a next pointer";

            EXPECT_EQ(last_end_cid , MAX_CID) << "Last version doesn't end with MAX_CID";
          }
        }
      } else {
        EXPECT_TRUE(tile_group_header->GetNextItemPointer(tuple_slot).IsNull()) << "Invalid tuple must not have next item pointer";
      }
    }
    LOG_INFO("[OK] oldest-to-newest version chain validated");
  }

  gc_manager.StartGC();
}

TEST_F(MVCCTest, SingleThreadVersionChainTest) {
  auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance();
  std::unique_ptr<storage::DataTable> table(
      TransactionTestsUtil::CreateTable());
  // read, read, read, read, update, read, read not exist
  // another txn read
  {
    TransactionScheduler scheduler(2, table.get(), &txn_manager);
    scheduler.Txn(0).Read(0);
    scheduler.Txn(0).Read(0);
    scheduler.Txn(0).Read(0);
    scheduler.Txn(0).Read(0);
    scheduler.Txn(0).Update(0, 1);
    scheduler.Txn(0).Read(0);
    scheduler.Txn(0).Read(100);
    scheduler.Txn(0).Commit();
    scheduler.Txn(1).Read(0);
    scheduler.Txn(1).Commit();

    scheduler.Run();

    ValidateMVCC_OldToNew(table.get());
  }

  // update, update, update, update, read
  {
    TransactionScheduler scheduler(1, table.get(), &txn_manager);
    scheduler.Txn(0).Update(0, 1);
    scheduler.Txn(0).Update(0, 2);
    scheduler.Txn(0).Update(0, 3);
    scheduler.Txn(0).Update(0, 4);
    scheduler.Txn(0).Read(0);
    scheduler.Txn(0).Commit();

    scheduler.Run();

    ValidateMVCC_OldToNew(table.get());
  }

  // delete not exist, delete exist, read deleted, update deleted,
  // read deleted, insert back, update inserted, read newly updated,
  // delete inserted, read deleted
  {
    TransactionScheduler scheduler(1, table.get(), &txn_manager);
    scheduler.Txn(0).Delete(100);
    scheduler.Txn(0).Delete(0);
    scheduler.Txn(0).Read(0);
    scheduler.Txn(0).Update(0, 1);
    scheduler.Txn(0).Read(0);
    scheduler.Txn(0).Insert(0, 2);
    scheduler.Txn(0).Update(0, 3);
    scheduler.Txn(0).Read(0);
    scheduler.Txn(0).Delete(0);
    scheduler.Txn(0).Read(0);
    scheduler.Txn(0).Commit();

    scheduler.Run();

    ValidateMVCC_OldToNew(table.get());
  }

  // insert, delete inserted, read deleted, insert again, delete again
  // read deleted, insert again, read inserted, update inserted, read updated
  {
    TransactionScheduler scheduler(1, table.get(), &txn_manager);

    scheduler.Txn(0).Insert(1000, 0);
    scheduler.Txn(0).Delete(1000);
    scheduler.Txn(0).Read(1000);
    scheduler.Txn(0).Insert(1000, 1);
    scheduler.Txn(0).Delete(1000);
    scheduler.Txn(0).Read(1000);
    scheduler.Txn(0).Insert(1000, 2);
    scheduler.Txn(0).Read(1000);
    scheduler.Txn(0).Update(1000, 3);
    scheduler.Txn(0).Read(1000);
    scheduler.Txn(0).Commit();

    scheduler.Run();

    ValidateMVCC_OldToNew(table.get());
  }
}

TEST_F(MVCCTest, AbortVersionChainTest) {
  auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance();
  std::unique_ptr<storage::DataTable> table(
      TransactionTestsUtil::CreateTable());
  {
    TransactionScheduler scheduler(2, table.get(), &txn_manager);
    scheduler.Txn(0).Update(0, 100);
    scheduler.Txn(0).Abort();
    scheduler.Txn(1).Read(0);
    scheduler.Txn(1).Commit();

    scheduler.Run();

    ValidateMVCC_OldToNew(table.get());
  }

  {
    TransactionScheduler scheduler(2, table.get(), &txn_manager);
    scheduler.Txn(0).Insert(100, 0);
    scheduler.Txn(0).Abort();
    scheduler.Txn(1).Read(100);
    scheduler.Txn(1).Commit();

    scheduler.Run();

    ValidateMVCC_OldToNew(table.get());
  }
}

TEST_F(MVCCTest, VersionChainTest) {
  const int num_txn = 5;
  const int scale = 20;
  const int num_key = 256;
  srand(15721);

  std::unique_ptr<storage::DataTable> table(
      TransactionTestsUtil::CreateTable(num_key));
  auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance();

  TransactionScheduler scheduler(num_txn, table.get(), &txn_manager);
  scheduler.SetConcurrent(true);
  for (int i = 0; i < num_txn; i++) {
    for (int j = 0; j < scale; j++) {
      // randomly select two uniq keys
      int key1 = rand() % num_key;
      int key2 = rand() % num_key;
      int delta = rand() % 1000;
      // Store substracted value
      scheduler.Txn(i).ReadStore(key1, -delta);
      scheduler.Txn(i).Update(key1, TXN_STORED_VALUE);
      // Store increased value
      scheduler.Txn(i).ReadStore(key2, delta);
      scheduler.Txn(i).Update(key2, TXN_STORED_VALUE);
    }
    scheduler.Txn(i).Commit();
  }
  scheduler.Run();

  // Read all values
  TransactionScheduler scheduler2(1, table.get(), &txn_manager);
  for (int i = 0; i < num_key; i++) {
    scheduler2.Txn(0).Read(i);
  }
  scheduler2.Txn(0).Commit();
  scheduler2.Run();

  ValidateMVCC_OldToNew(table.get());
}

}  // End test namespace
}  // End peloton namespace
<|endoftext|>


<commit_before>#include <boost/version.hpp>
#include <boost/detail/lightweight_test.hpp>
#include <iostream>
#include <mapnik/params.hpp>
#include <mapnik/boolean.hpp>

int main( int, char*[] )
{

    mapnik::parameters params;

    // true
    //params["bool"] = true;
    //BOOST_TEST( (params.get<mapnik::boolean>("bool") && *params.get<mapnik::boolean>("bool") == true));

    params["bool"] = "true";
    BOOST_TEST( (params.get<mapnik::boolean>("bool") && *params.get<mapnik::boolean>("bool") == true));

    //params["bool"] = 1;
    //BOOST_TEST( (params.get<mapnik::boolean>("bool") && *params.get<mapnik::boolean>("bool") == true));

    params["bool"] = "1";
    BOOST_TEST( (params.get<mapnik::boolean>("bool") && *params.get<mapnik::boolean>("bool") == true));

    params["bool"] = "True";
    BOOST_TEST( (params.get<mapnik::boolean>("bool") && *params.get<mapnik::boolean>("bool") == true));

    params["bool"] = "on";
    BOOST_TEST( (params.get<mapnik::boolean>("bool") && *params.get<mapnik::boolean>("bool") == true));

    params["bool"] = "yes";
    BOOST_TEST( (params.get<mapnik::boolean>("bool") && *params.get<mapnik::boolean>("bool") == true));

    // false
    //params["bool"] = false;
    //BOOST_TEST( (params.get<mapnik::boolean>("bool") && *params.get<mapnik::boolean>("bool") == false) );

    params["bool"] = "false";
    BOOST_TEST( (params.get<mapnik::boolean>("bool") && *params.get<mapnik::boolean>("bool") == false) );

    //params["bool"] = 0;
    //BOOST_TEST( (params.get<mapnik::boolean>("bool") && *params.get<mapnik::boolean>("bool") == false));

    params["bool"] = "0";
    BOOST_TEST( (params.get<mapnik::boolean>("bool") && *params.get<mapnik::boolean>("bool") == false));

    params["bool"] = "False";
    BOOST_TEST( (params.get<mapnik::boolean>("bool") && *params.get<mapnik::boolean>("bool") == false));

    params["bool"] = "off";
    BOOST_TEST( (params.get<mapnik::boolean>("bool") && *params.get<mapnik::boolean>("bool") == false));

    params["bool"] = "no";
    BOOST_TEST( (params.get<mapnik::boolean>("bool") && *params.get<mapnik::boolean>("bool") == false));

    // strings
    params["string"] = "hello";
    BOOST_TEST( (params.get<std::string>("string") && *params.get<std::string>("string") == "hello") );

    // int
    params["int"] = 1LL;
    BOOST_TEST( (params.get<int>("int") && *params.get<int>("int") == 1) );

    // double
    params["double"] = 1.5;
    BOOST_TEST( (params.get<double>("double") && *params.get<double>("double") == 1.5) );

    // value_null
    params["null"] = mapnik::value_null();
    //BOOST_TEST( (params.get<mapnik::value_null>("null")/* && *params.get<mapnik::value_null>("null") == mapnik::value_null()*/) );

    if (!::boost::detail::test_errors()) {
        std::clog << "C++ parameters: \x1b[1;32m✓ \x1b[0m\n";
#if BOOST_VERSION >= 104600
        ::boost::detail::report_errors_remind().called_report_errors_function = true;
#endif
    } else {
        return ::boost::report_errors();
    }
}
<commit_msg>+ remove LL<commit_after>#include <boost/version.hpp>
#include <boost/detail/lightweight_test.hpp>
#include <iostream>
#include <mapnik/params.hpp>
#include <mapnik/boolean.hpp>

int main( int, char*[] )
{

    mapnik::parameters params;

    // true
    //params["bool"] = true;
    //BOOST_TEST( (params.get<mapnik::boolean>("bool") && *params.get<mapnik::boolean>("bool") == true));

    params["bool"] = "true";
    BOOST_TEST( (params.get<mapnik::boolean>("bool") && *params.get<mapnik::boolean>("bool") == true));

    //params["bool"] = 1;
    //BOOST_TEST( (params.get<mapnik::boolean>("bool") && *params.get<mapnik::boolean>("bool") == true));

    params["bool"] = "1";
    BOOST_TEST( (params.get<mapnik::boolean>("bool") && *params.get<mapnik::boolean>("bool") == true));

    params["bool"] = "True";
    BOOST_TEST( (params.get<mapnik::boolean>("bool") && *params.get<mapnik::boolean>("bool") == true));

    params["bool"] = "on";
    BOOST_TEST( (params.get<mapnik::boolean>("bool") && *params.get<mapnik::boolean>("bool") == true));

    params["bool"] = "yes";
    BOOST_TEST( (params.get<mapnik::boolean>("bool") && *params.get<mapnik::boolean>("bool") == true));

    // false
    //params["bool"] = false;
    //BOOST_TEST( (params.get<mapnik::boolean>("bool") && *params.get<mapnik::boolean>("bool") == false) );

    params["bool"] = "false";
    BOOST_TEST( (params.get<mapnik::boolean>("bool") && *params.get<mapnik::boolean>("bool") == false) );

    //params["bool"] = 0;
    //BOOST_TEST( (params.get<mapnik::boolean>("bool") && *params.get<mapnik::boolean>("bool") == false));

    params["bool"] = "0";
    BOOST_TEST( (params.get<mapnik::boolean>("bool") && *params.get<mapnik::boolean>("bool") == false));

    params["bool"] = "False";
    BOOST_TEST( (params.get<mapnik::boolean>("bool") && *params.get<mapnik::boolean>("bool") == false));

    params["bool"] = "off";
    BOOST_TEST( (params.get<mapnik::boolean>("bool") && *params.get<mapnik::boolean>("bool") == false));

    params["bool"] = "no";
    BOOST_TEST( (params.get<mapnik::boolean>("bool") && *params.get<mapnik::boolean>("bool") == false));

    // strings
    params["string"] = "hello";
    BOOST_TEST( (params.get<std::string>("string") && *params.get<std::string>("string") == "hello") );

    // int
    params["int"] = 1;
    BOOST_TEST( (params.get<int>("int") && *params.get<int>("int") == 1) );

    // double
    params["double"] = 1.5;
    BOOST_TEST( (params.get<double>("double") && *params.get<double>("double") == 1.5) );

    // value_null
    params["null"] = mapnik::value_null();
    //BOOST_TEST( (params.get<mapnik::value_null>("null")/* && *params.get<mapnik::value_null>("null") == mapnik::value_null()*/) );

    if (!::boost::detail::test_errors()) {
        std::clog << "C++ parameters: \x1b[1;32m✓ \x1b[0m\n";
#if BOOST_VERSION >= 104600
        ::boost::detail::report_errors_remind().called_report_errors_function = true;
#endif
    } else {
        return ::boost::report_errors();
    }
}
<|endoftext|>


<commit_before>#include "instanciate.h"

using namespace Yuni;

namespace Nany
{
namespace Pass
{
namespace Instanciate
{

	void SequenceBuilder::tryUnrefObject(uint32_t lvid)
	{
		auto& frame = atomStack.back();
		if (not frame.verify(lvid))
			return;

		auto& cdef  = cdeftable.classdefFollowClassMember(CLID{frame.atomid, lvid});
		if (not canBeAcquired(cdef)) // do nothing if builtin
			return;

		auto* atom = cdeftable.findClassdefAtom(cdef);
		if (unlikely(nullptr == atom))
		{
			ICE() << "invalid atom for 'unref' opcode";
			return;
		}

		if (0 == atom->classinfo.dtor.atomid)
		{
			if (unlikely(not instanciateAtomClassDestructor(*atom, lvid)))
				return;
			assert(atom->classinfo.dtor.atomid != 0);
		}

		if (canGenerateCode())
			out.emitUnref(lvid, atom->classinfo.dtor.atomid, atom->classinfo.dtor.instanceid);
	}

	void SequenceBuilder::visit(const IR::ISA::Operand<IR::ISA::Op::ref>& operands)
	{
		if (not atomStack.back().verify(operands.lvid))
			return;

		if (canGenerateCode())
		{
			if (canBeAcquired(operands.lvid))
				out.emitRef(operands.lvid); // manual var acquisition
		}
	}

} // namespace Instanciate
} // namespace Pass
} // namespace Nany
<commit_msg>suppress spurious err messages when a dtor can't be called<commit_after>#include "instanciate.h"

using namespace Yuni;

namespace Nany
{
namespace Pass
{
namespace Instanciate
{

	void SequenceBuilder::tryUnrefObject(uint32_t lvid)
	{
		auto& frame = atomStack.back();
		if (not frame.verify(lvid))
			return;

		auto& cdef  = cdeftable.classdefFollowClassMember(CLID{frame.atomid, lvid});
		if (not canBeAcquired(cdef)) // do nothing if builtin
			return;

		auto* atom = cdeftable.findClassdefAtom(cdef);
		if (unlikely(nullptr == atom))
		{
			ICE() << "invalid atom for 'unref' opcode";
			return frame.invalidate(lvid);
		}

		if (0 == atom->classinfo.dtor.atomid)
		{
			if (unlikely(not instanciateAtomClassDestructor(*atom, lvid)))
				return frame.invalidate(lvid);
			assert(atom->classinfo.dtor.atomid != 0);
		}

		if (canGenerateCode())
			out.emitUnref(lvid, atom->classinfo.dtor.atomid, atom->classinfo.dtor.instanceid);
	}

	void SequenceBuilder::visit(const IR::ISA::Operand<IR::ISA::Op::ref>& operands)
	{
		if (not atomStack.back().verify(operands.lvid))
			return;

		if (canGenerateCode())
		{
			if (canBeAcquired(operands.lvid))
				out.emitRef(operands.lvid); // manual var acquisition
		}
	}

} // namespace Instanciate
} // namespace Pass
} // namespace Nany
<|endoftext|>


<commit_before>/* Brainfuck interpreter using interpreter and composite patterns :) */

#include <exception>
#include <iostream>
#include <list>
#include <vector>
#include <map>
#include <string>
#include <algorithm>
#include <memory>

using namespace std;

struct Data
{
    vector<int> array;
    int ptr;
};

class AbstractExpression
{
    public:
        AbstractExpression() {}
        virtual ~AbstractExpression() {}
        virtual void add(shared_ptr<AbstractExpression>) {}
        virtual bool isComposite() {return false;}
        virtual void interpret(Data &) = 0;
        virtual void parse(const string &) {}
};

class IncrementByte: public AbstractExpression
{
    public:
        virtual void interpret(Data &data) {
            data.array[data.ptr]++;
        }
};

class DecrementByte: public AbstractExpression
{
    public:
        virtual void interpret(Data &data) {
            data.array[data.ptr]--;
        }
};

class IncrementPtr: public AbstractExpression
{
    public:
        virtual void interpret(Data &data) {
            data.ptr++;
            if(data.array.size()==data.ptr) data.array.push_back(0);
        }
};

class DecrementPtr: public AbstractExpression
{
    public:
        virtual void interpret(Data &data) {
            data.ptr--;
            if(data.ptr<0) throw out_of_range("Negative value of pointer");
        }
};

class Output: public AbstractExpression
{
    public:
        virtual void interpret(Data &data) {
            cout<<char(data.array[data.ptr]);
        }
};

class Input: public AbstractExpression
{
    public:
        virtual void interpret(Data &data) {
            char input;
            cin>>input;
            data.array[data.ptr] = static_cast<char>(input);
        }
};

typedef shared_ptr<AbstractExpression> AbstractExpressionPtr;

class CompositeExpression: public AbstractExpression
{
    private:
        list<AbstractExpressionPtr> expTree;
    public:
        CompositeExpression(): expTree() {}

        virtual ~CompositeExpression() {}

        virtual bool isComposite() {return true;}

        virtual void add(AbstractExpressionPtr exp) {expTree.push_back(exp);}

        virtual void interpret(Data &data) {
            for(list<AbstractExpressionPtr>::iterator it=expTree.begin(); it!=expTree.end(); it++) {
                if((*it)->isComposite()) {
                    while(data.array[data.ptr])
                        (*it)->interpret(data);
                }
                else {
                    (*it)->interpret(data);
                }
            }
        }
};

class Parser
{
    private:
        map<char, AbstractExpressionPtr> expMap;
        list<char> chars;
    public:
        Parser() {
            chars.push_back('+'); expMap[chars.back()] = AbstractExpressionPtr(new IncrementByte);
            chars.push_back('-'); expMap[chars.back()] = AbstractExpressionPtr(new DecrementByte);
            chars.push_back('>'); expMap[chars.back()] = AbstractExpressionPtr(new IncrementPtr);
            chars.push_back('<'); expMap[chars.back()] = AbstractExpressionPtr(new DecrementPtr);
            chars.push_back('.'); expMap[chars.back()] = AbstractExpressionPtr(new Output);
            chars.push_back(','); expMap[chars.back()] = AbstractExpressionPtr(new Input);
        }

        AbstractExpressionPtr buildTree(const string & code) {
            AbstractExpressionPtr syntaxTreePtr(new CompositeExpression);
            int skip(0);
            for(int i=0; i<code.size(); i++) {
                if(skip) {
                    if(code[i] == '[') skip++;
                    if(code[i] == ']') skip--;
                    continue;
                }
                if(find(chars.begin(), chars.end(), code[i]) != chars.end()) {
                    syntaxTreePtr->add(expMap[code[i]]);
                }
                else if (code[i] == '[') {
                    AbstractExpressionPtr exp = buildTree(code.substr(i+1));
                    syntaxTreePtr->add(exp);
                    skip = 1;
                }
                else if(code[i]==']') break;
            }
            return syntaxTreePtr;
        }
};

int main()
{
    Data data; data.array.assign(1,0); data.ptr = 0;
    string code("++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>.");
    //string code(",[.[-],]");
    Parser parser;
    AbstractExpressionPtr syntaxTreePtr = parser.buildTree(code);
    syntaxTreePtr->interpret(data);
}
<commit_msg>Simplify Parser class<commit_after>/* Brainfuck interpreter using interpreter and composite patterns :) */

#include <exception>
#include <iostream>
#include <list>
#include <vector>
#include <map>
#include <string>
#include <algorithm>
#include <memory>

using namespace std;

struct Data
{
    vector<int> array;
    int ptr;
};

class AbstractExpression
{
    public:
        AbstractExpression() {}
        virtual ~AbstractExpression() {}
        virtual void add(shared_ptr<AbstractExpression>) {}
        virtual bool isComposite() {return false;}
        virtual void interpret(Data &) = 0;
        virtual void parse(const string &) {}
};

class IncrementByte: public AbstractExpression
{
    public:
        virtual void interpret(Data &data) {
            data.array[data.ptr]++;
        }
};

class DecrementByte: public AbstractExpression
{
    public:
        virtual void interpret(Data &data) {
            data.array[data.ptr]--;
        }
};

class IncrementPtr: public AbstractExpression
{
    public:
        virtual void interpret(Data &data) {
            data.ptr++;
            if(data.array.size()==data.ptr) data.array.push_back(0);
        }
};

class DecrementPtr: public AbstractExpression
{
    public:
        virtual void interpret(Data &data) {
            data.ptr--;
            if(data.ptr<0) throw out_of_range("Negative value of pointer");
        }
};

class Output: public AbstractExpression
{
    public:
        virtual void interpret(Data &data) {
            cout<<char(data.array[data.ptr]);
        }
};

class Input: public AbstractExpression
{
    public:
        virtual void interpret(Data &data) {
            char input;
            cin>>input;
            data.array[data.ptr] = static_cast<char>(input);
        }
};

typedef shared_ptr<AbstractExpression> AbstractExpressionPtr;

class CompositeExpression: public AbstractExpression
{
    private:
        list<AbstractExpressionPtr> expTree;
    public:
        CompositeExpression(): expTree() {}

        virtual ~CompositeExpression() {}

        virtual bool isComposite() {return true;}

        virtual void add(AbstractExpressionPtr exp) {expTree.push_back(exp);}

        virtual void interpret(Data &data) {
            for(list<AbstractExpressionPtr>::iterator it=expTree.begin(); it!=expTree.end(); it++) {
                if((*it)->isComposite()) {
                    while(data.array[data.ptr])
                        (*it)->interpret(data);
                }
                else {
                    (*it)->interpret(data);
                }
            }
        }
};

class Parser
{
    private:
        map<char, AbstractExpressionPtr> expMap;
    public:
        Parser() {
            expMap['+'] = AbstractExpressionPtr(new IncrementByte);
            expMap['-'] = AbstractExpressionPtr(new DecrementByte);
            expMap['>'] = AbstractExpressionPtr(new IncrementPtr);
            expMap['<'] = AbstractExpressionPtr(new DecrementPtr);
            expMap['.'] = AbstractExpressionPtr(new Output);
            expMap[','] = AbstractExpressionPtr(new Input);
        }

        AbstractExpressionPtr buildTree(const string & code) {
            AbstractExpressionPtr syntaxTreePtr(new CompositeExpression);
            int skip(0);
            for(int i=0; i<code.size(); i++) {
                if(skip) {
                    if(code[i] == '[') skip++;
                    if(code[i] == ']') skip--;
                    continue;
                }
                if(expMap.find(code[i]) != expMap.end()) {
                    syntaxTreePtr->add(expMap[code[i]]);
                }
                else if (code[i] == '[') {
                    AbstractExpressionPtr exp = buildTree(code.substr(i+1));
                    syntaxTreePtr->add(exp);
                    skip = 1;
                }
                else if(code[i]==']') break;
            }
            return syntaxTreePtr;
        }
};

int main()
{
    Data data; data.array.assign(1,0); data.ptr = 0;
    string code("++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>.");
    //string code(",[.[-],]");
    Parser parser;
    AbstractExpressionPtr syntaxTreePtr = parser.buildTree(code);
    syntaxTreePtr->interpret(data);
}
<|endoftext|>


<commit_before><commit_msg>doubly_linked_list<commit_after><|endoftext|>


<commit_before>#ifndef BFC_COMBINE_INC_VISITOR_HPP
#define BFC_COMBINE_INC_VISITOR_HPP

#include "ast/mod.hpp"
#include "ast/base.hpp"
#include "test_visitor.hpp"
#include "types.h"

namespace bfc {
namespace ast {

class combine_inc_visitor : public opt_seq_base_visitor {

public:

    enum node_type {
        ADD = 0,
        SUB
    };

    status visit(add &node) {
        // discard any zero value node
        if (node.value() == 0) {
            return CONTINUE;
        }
        // Only attempt to combine if there is a previous node
        if (!opt_seq.empty()) {
            // try to combine with the previous node if possible
            try_combine_inc_visitor v(node.offset(), node.value(), true);
            if (opt_seq.back().accept(v) == CONTINUE) {
                opt_seq.pop_back();
                // discard the combined node if it is 0
                if (v.new_value() != 0) {
                    if (v.type() == ADD) {
                        opt_seq.emplace_back(new add(node.loc(), node.offset(), v.new_value()));
                    } else {
                        opt_seq.emplace_back(new sub(node.loc(), node.offset(), v.new_value()));
                    }
                }
                return CONTINUE;
            }
        }
        // else make node copy
        return opt_seq_base_visitor::handle_add(node);
    }

    status visit(const add &node) {
        // discard any zero value node
        if (node.value() == 0) {
            return CONTINUE;
        }
        // Only attempt to combine if there is a previous node
        if (!opt_seq.empty()) {
            // try to combine with the previous node if possible
            try_combine_inc_visitor v(node.offset(), node.value(), true);
            if (opt_seq.back().accept(v) == CONTINUE) {
                opt_seq.pop_back();
                // discard the combined node if it is 0
                if (v.new_value() != 0) {
                    if (v.type() == ADD) {
                        opt_seq.emplace_back(new add(node.loc(), node.offset(), v.new_value()));
                    } else {
                        opt_seq.emplace_back(new sub(node.loc(), node.offset(), v.new_value()));
                    }
                }
                return CONTINUE;
            }
        }
        // else make node copy
        return opt_seq_base_visitor::handle_add(node);
    }

    status visit(sub &node) {
        // discard any zero value node
        if (node.value() == 0) {
            return CONTINUE;
        }
        // Only attempt to combine if there is a previous node
        if (!opt_seq.empty()) {
            // try to combine with the previous node if possible
            try_combine_inc_visitor v(node.offset(), node.value(), false);
            if (opt_seq.back().accept(v) == CONTINUE) {
                opt_seq.pop_back();
                // discard the combined node if it is 0
                if (v.new_value() != 0) {
                    if (v.type() == ADD) {
                        opt_seq.emplace_back(new add(node.loc(), node.offset(), v.new_value()));
                    } else {
                        opt_seq.emplace_back(new sub(node.loc(), node.offset(), v.new_value()));
                    }
                    return CONTINUE;
                }
            }
        }
        // else make node copy
        return opt_seq_base_visitor::handle_sub(node);
    }

    status visit(const sub &node) {
        // discard any zero value node
        if (node.value() == 0) {
            return CONTINUE;
        }
        // Only attempt to combine if there is a previous node
        if (!opt_seq.empty()) {
            // try to combine with the previous node if possible
            try_combine_inc_visitor v(node.offset(), node.value(), false);
            if (opt_seq.back().accept(v) == CONTINUE) {
                opt_seq.pop_back();
                // discard the combined node if it is 0
                if (v.new_value() != 0) {
                    if (v.type() == ADD) {
                        opt_seq.emplace_back(new add(node.loc(), node.offset(), v.new_value()));
                    } else {
                        opt_seq.emplace_back(new sub(node.loc(), node.offset(), v.new_value()));
                    }
                    return CONTINUE;
                }
                return CONTINUE;
            }
        }
        // else make node copy
        return opt_seq_base_visitor::handle_sub(node);
    }

private:

    class try_combine_inc_visitor : public test_visitor {

        public:
            try_combine_inc_visitor(ptrdiff_t offset, bf_value val, bool isAdd) :
                next_off(offset), next_val(val), isAdd(isAdd) {}

            bf_value new_value() {
                return new_val;
            }

            node_type type() {
                return type;
            }

            status visit(add &node) {
                if (node.offset() != next_off) {
                    return BREAK;
                }
                new_val = node.value();
                isAdd ? new_val += next_val : new_val -= next_val;
                type = ADD;
                return CONTINUE;
            }

            status visit(const add &node) {
                if (node.offset() != next_off) {
                    return BREAK;
                }
                new_val = node.value();
                isAdd ? new_val += next_val : new_val -= next_val;
                type = ADD;
                return CONTINUE;
            }

            status visit(sub &node) {
                if (node.offset() != next_off) {
                    return BREAK;
                }
                new_val = node.value();
                isAdd ? new_val -= next_val : new_val += next_val;
                type = SUB;
                return CONTINUE;
            }

            status visit(const sub &node) {
                if (node.offset() != next_off) {
                    return BREAK;
                }
                new_val = node.value();
                isAdd ? new_val -= next_val : new_val += next_val;
                type = SUB;
                return CONTINUE;
            }

        private:
            bool isAdd;
            ptrdiff_t next_off;
            bf_value next_val;
            bf_value new_val;
            node_type type;
    };

};

}
}

#endif /* !BFC_COMBINE_INC_VISITOR_HPP */
<commit_msg>Rename var<commit_after>#ifndef BFC_COMBINE_INC_VISITOR_HPP
#define BFC_COMBINE_INC_VISITOR_HPP

#include "ast/mod.hpp"
#include "ast/base.hpp"
#include "test_visitor.hpp"
#include "types.h"

namespace bfc {
namespace ast {

class combine_inc_visitor : public opt_seq_base_visitor {

public:

    enum node_type {
        ADD = 0,
        SUB
    };

    status visit(add &node) {
        // discard any zero value node
        if (node.value() == 0) {
            return CONTINUE;
        }
        // Only attempt to combine if there is a previous node
        if (!opt_seq.empty()) {
            // try to combine with the previous node if possible
            try_combine_inc_visitor v(node.offset(), node.value(), true);
            if (opt_seq.back().accept(v) == CONTINUE) {
                opt_seq.pop_back();
                // discard the combined node if it is 0
                if (v.new_value() != 0) {
                    if (v.type() == ADD) {
                        opt_seq.emplace_back(new add(node.loc(), node.offset(), v.new_value()));
                    } else {
                        opt_seq.emplace_back(new sub(node.loc(), node.offset(), v.new_value()));
                    }
                }
                return CONTINUE;
            }
        }
        // else make node copy
        return opt_seq_base_visitor::handle_add(node);
    }

    status visit(const add &node) {
        // discard any zero value node
        if (node.value() == 0) {
            return CONTINUE;
        }
        // Only attempt to combine if there is a previous node
        if (!opt_seq.empty()) {
            // try to combine with the previous node if possible
            try_combine_inc_visitor v(node.offset(), node.value(), true);
            if (opt_seq.back().accept(v) == CONTINUE) {
                opt_seq.pop_back();
                // discard the combined node if it is 0
                if (v.new_value() != 0) {
                    if (v.type() == ADD) {
                        opt_seq.emplace_back(new add(node.loc(), node.offset(), v.new_value()));
                    } else {
                        opt_seq.emplace_back(new sub(node.loc(), node.offset(), v.new_value()));
                    }
                }
                return CONTINUE;
            }
        }
        // else make node copy
        return opt_seq_base_visitor::handle_add(node);
    }

    status visit(sub &node) {
        // discard any zero value node
        if (node.value() == 0) {
            return CONTINUE;
        }
        // Only attempt to combine if there is a previous node
        if (!opt_seq.empty()) {
            // try to combine with the previous node if possible
            try_combine_inc_visitor v(node.offset(), node.value(), false);
            if (opt_seq.back().accept(v) == CONTINUE) {
                opt_seq.pop_back();
                // discard the combined node if it is 0
                if (v.new_value() != 0) {
                    if (v.type() == ADD) {
                        opt_seq.emplace_back(new add(node.loc(), node.offset(), v.new_value()));
                    } else {
                        opt_seq.emplace_back(new sub(node.loc(), node.offset(), v.new_value()));
                    }
                    return CONTINUE;
                }
            }
        }
        // else make node copy
        return opt_seq_base_visitor::handle_sub(node);
    }

    status visit(const sub &node) {
        // discard any zero value node
        if (node.value() == 0) {
            return CONTINUE;
        }
        // Only attempt to combine if there is a previous node
        if (!opt_seq.empty()) {
            // try to combine with the previous node if possible
            try_combine_inc_visitor v(node.offset(), node.value(), false);
            if (opt_seq.back().accept(v) == CONTINUE) {
                opt_seq.pop_back();
                // discard the combined node if it is 0
                if (v.new_value() != 0) {
                    if (v.type() == ADD) {
                        opt_seq.emplace_back(new add(node.loc(), node.offset(), v.new_value()));
                    } else {
                        opt_seq.emplace_back(new sub(node.loc(), node.offset(), v.new_value()));
                    }
                    return CONTINUE;
                }
                return CONTINUE;
            }
        }
        // else make node copy
        return opt_seq_base_visitor::handle_sub(node);
    }

private:

    class try_combine_inc_visitor : public test_visitor {

        public:
            try_combine_inc_visitor(ptrdiff_t offset, bf_value val, bool isAdd) :
                next_off(offset), next_val(val), isAdd(isAdd) {}

            bf_value new_value() {
                return new_val;
            }

            node_type type() {
                return this_type;
            }

            status visit(add &node) {
                if (node.offset() != next_off) {
                    return BREAK;
                }
                new_val = node.value();
                isAdd ? new_val += next_val : new_val -= next_val;
                type = ADD;
                return CONTINUE;
            }

            status visit(const add &node) {
                if (node.offset() != next_off) {
                    return BREAK;
                }
                new_val = node.value();
                isAdd ? new_val += next_val : new_val -= next_val;
                type = ADD;
                return CONTINUE;
            }

            status visit(sub &node) {
                if (node.offset() != next_off) {
                    return BREAK;
                }
                new_val = node.value();
                isAdd ? new_val -= next_val : new_val += next_val;
                type = SUB;
                return CONTINUE;
            }

            status visit(const sub &node) {
                if (node.offset() != next_off) {
                    return BREAK;
                }
                new_val = node.value();
                isAdd ? new_val -= next_val : new_val += next_val;
                type = SUB;
                return CONTINUE;
            }

        private:
            bool isAdd;
            ptrdiff_t next_off;
            bf_value next_val;
            bf_value new_val;
            node_type this_type;
    };

};

}
}

#endif /* !BFC_COMBINE_INC_VISITOR_HPP */
<|endoftext|>


<commit_before>#include "TPAdapter.h"

#include <fstream>

#include <drag2d.h>

namespace libcoco
{

void TPAdapter::Load(const char* filename)
{
	Json::Value value;
	Json::Reader reader;
	std::locale::global(std::locale(""));
	std::ifstream fin(filename);
	std::locale::global(std::locale("C"));
	reader.parse(fin, value);
	fin.close();

	m_width = value["meta"]["size"]["w"].asInt();
	m_height = value["meta"]["size"]["h"].asInt();

	std::string str = value["meta"]["scale"].asString();
	m_invscale = atof(str.c_str());

	int i = 0;
	Json::Value frameValue = value["frames"][i++];
	while (!frameValue.isNull()) {
		Entry entry;
		Load(frameValue, entry);
		m_frames.push_back(entry);
		frameValue = value["frames"][i++];
	}
}

void TPAdapter::Load(const Json::Value& value, Entry& entry)
{
	entry.filename = value["filename"].asString();
	StringTools::toLower(entry.filename);
	Load(value["frame"], entry.frame);
	entry.rotated = value["rotated"].asBool();
	entry.trimmed = value["trimmed"].asBool();
	Load(value["spriteSourceSize"], entry.sprite_source_size);
	entry.src_width = value["sourceSize"]["w"].asInt();
	entry.src_height = value["sourceSize"]["h"].asInt();
}

void TPAdapter::Load(const Json::Value& value, Region& region)
{
	region.x = value["x"].asInt();
	region.y = value["y"].asInt();
	region.w = value["w"].asInt();
	region.h = value["h"].asInt();
}

} // d2d<commit_msg>[FIXED] 打包时路径\和/的处理<commit_after>#include "TPAdapter.h"

#include <fstream>

#include <drag2d.h>

namespace libcoco
{

void TPAdapter::Load(const char* filename)
{
	Json::Value value;
	Json::Reader reader;
	std::locale::global(std::locale(""));
	std::ifstream fin(filename);
	std::locale::global(std::locale("C"));
	reader.parse(fin, value);
	fin.close();

	m_width = value["meta"]["size"]["w"].asInt();
	m_height = value["meta"]["size"]["h"].asInt();

	std::string str = value["meta"]["scale"].asString();
	m_invscale = atof(str.c_str());

	int i = 0;
	Json::Value frameValue = value["frames"][i++];
	while (!frameValue.isNull()) {
		Entry entry;
		Load(frameValue, entry);
		m_frames.push_back(entry);
		frameValue = value["frames"][i++];
	}
}

void TPAdapter::Load(const Json::Value& value, Entry& entry)
{
	entry.filename = value["filename"].asString();
	StringTools::toLower(entry.filename);
	d2d::FilenameTools::formatSeparators(entry.filename);

	Load(value["frame"], entry.frame);
	entry.rotated = value["rotated"].asBool();
	entry.trimmed = value["trimmed"].asBool();
	Load(value["spriteSourceSize"], entry.sprite_source_size);
	entry.src_width = value["sourceSize"]["w"].asInt();
	entry.src_height = value["sourceSize"]["h"].asInt();
}

void TPAdapter::Load(const Json::Value& value, Region& region)
{
	region.x = value["x"].asInt();
	region.y = value["y"].asInt();
	region.w = value["w"].asInt();
	region.h = value["h"].asInt();
}

} // d2d<|endoftext|>


<commit_before>#ifndef __CONCURRENCY_CORO_POOL_HPP__
#define __CONCURRENCY_CORO_POOL_HPP__

#include "errors.hpp"
#include "concurrency/queue/passive_producer.hpp"
#include "concurrency/drain_semaphore.hpp"

/* coro_pool_t maintains a bunch of coroutines; when you give it tasks, it
distributes them among the coroutines. It draws its tasks from a
`passive_producer_t<boost::function<void()> >*`. */

class coro_pool_t :
    public home_thread_mixin_t,
    private watchable_t<bool>::watcher_t
{
public:
    coro_pool_t(size_t worker_count_, passive_producer_t<boost::function<void()> > *source) :
        source(source),
        max_worker_count(worker_count_),
        active_worker_count(0)
    {
        rassert(max_worker_count > 0);
        on_watchable_changed();   // Start process if necessary
        source->available->add_watcher(this);
    }

    ~coro_pool_t() {
        assert_thread();
        source->available->remove_watcher(this);
        coro_drain_semaphore.drain();
        rassert(active_worker_count == 0);
    }

    void rethread(int new_thread) {
        /* Can't rethread while there are active operations */
        rassert(active_worker_count == 0);
        rassert(!source->available->get());
        real_home_thread = new_thread;
    }

private:
    passive_producer_t<boost::function<void()> > *source;

    void on_watchable_changed() {
        assert_thread();
        while (source->available->get() && active_worker_count < max_worker_count) {
            coro_t::spawn_now(boost::bind(
                &coro_pool_t::worker_run,
                    this,
                    drain_semaphore_t::lock_t(&coro_drain_semaphore)
                ));
        }
    }

    int max_worker_count, active_worker_count;

    drain_semaphore_t coro_drain_semaphore;

    void worker_run(UNUSED drain_semaphore_t::lock_t coro_drain_semaphore_lock) {
        assert_thread();
        ++active_worker_count;
        rassert(active_worker_count <= max_worker_count);
        while (source->available->get()) {
            /* Pop the task that we are going to do off the queue */
            boost::function<void()> task = source->pop();
            task();   // Perform the task
            assert_thread();   // Make sure that `task()` didn't mess with us
        }
        --active_worker_count;
    }
};

#endif /* __CONCURRENCY_CORO_POOL_HPP__ */

<commit_msg>Added a note about coro_pool_t.<commit_after>#ifndef __CONCURRENCY_CORO_POOL_HPP__
#define __CONCURRENCY_CORO_POOL_HPP__

#include "errors.hpp"
#include "concurrency/queue/passive_producer.hpp"
#include "concurrency/drain_semaphore.hpp"

/* coro_pool_t maintains a bunch of coroutines; when you give it tasks, it
distributes them among the coroutines. It draws its tasks from a
`passive_producer_t<boost::function<void()> >*`.

Right now, a number of different things depent on the `coro_pool_t` finishing
all of its tasks and draining its `passive_producer_t` before its destructor
returns. */

class coro_pool_t :
    public home_thread_mixin_t,
    private watchable_t<bool>::watcher_t
{
public:
    coro_pool_t(size_t worker_count_, passive_producer_t<boost::function<void()> > *source) :
        source(source),
        max_worker_count(worker_count_),
        active_worker_count(0)
    {
        rassert(max_worker_count > 0);
        on_watchable_changed();   // Start process if necessary
        source->available->add_watcher(this);
    }

    ~coro_pool_t() {
        assert_thread();
        source->available->remove_watcher(this);
        coro_drain_semaphore.drain();
        rassert(active_worker_count == 0);
    }

    void rethread(int new_thread) {
        /* Can't rethread while there are active operations */
        rassert(active_worker_count == 0);
        rassert(!source->available->get());
        real_home_thread = new_thread;
    }

private:
    passive_producer_t<boost::function<void()> > *source;

    void on_watchable_changed() {
        assert_thread();
        while (source->available->get() && active_worker_count < max_worker_count) {
            coro_t::spawn_now(boost::bind(
                &coro_pool_t::worker_run,
                    this,
                    drain_semaphore_t::lock_t(&coro_drain_semaphore)
                ));
        }
    }

    int max_worker_count, active_worker_count;

    drain_semaphore_t coro_drain_semaphore;

    void worker_run(UNUSED drain_semaphore_t::lock_t coro_drain_semaphore_lock) {
        assert_thread();
        ++active_worker_count;
        rassert(active_worker_count <= max_worker_count);
        while (source->available->get()) {
            /* Pop the task that we are going to do off the queue */
            boost::function<void()> task = source->pop();
            task();   // Perform the task
            assert_thread();   // Make sure that `task()` didn't mess with us
        }
        --active_worker_count;
    }
};

#endif /* __CONCURRENCY_CORO_POOL_HPP__ */

<|endoftext|>


<commit_before>//=======================================================================
// Copyright (c) 2015-2016 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#include "asgard/driver.hpp"

extern "C" {
#include <lirc/lirc_client.h>
}

namespace {

// Configuration (this should be in a configuration file)
const char* server_socket_path = "/tmp/asgard_socket";
const char* client_socket_path = "/tmp/asgard_ir_socket";

asgard::driver_connector driver;

// The remote IDs
int source_id = -1;
int button_actuator_id = -1;

void stop(){
    std::cout << "asgard:ir: stop the driver" << std::endl;

    //Closes LIRC
    lirc_deinit();

    asgard::unregister_actuator(driver, source_id, button_actuator_id);
    asgard::unregister_source(driver, source_id);

    // Unlink the client socket
    unlink(client_socket_path);

    // Close the socket
    close(driver.socket_fd);
}

void terminate(int){
    stop();

    std::exit(0);
}

void ir_received(char* raw_code){
    std::string full_code(raw_code);

    auto code_end = full_code.find(' ');
    std::string code(full_code.begin(), full_code.begin() + code_end);

    auto repeat_end = full_code.find(' ', code_end + 1);
    std::string repeat(full_code.begin() + code_end + 1, full_code.begin() + repeat_end);

    auto key_end = full_code.find(' ', repeat_end + 1);
    std::string key(full_code.begin() + repeat_end + 1, full_code.begin() + key_end);

    std::cout << "asgard:ir: Received: " << code << ":" << repeat << ":" << key << std::endl;

    asgard::send_event(driver, source_id, button_actuator_id, key);
}

} //End of anonymous namespace

int main(){
    //Initiate LIRC. Exit on failure
    char lirc_name[] = "lirc";
    if(lirc_init(lirc_name, 1) == -1){
        std::cout << "asgard:ir: Failed to init LIRC" << std::endl;
        return 1;
    }

    // Open the connection
    if(!asgard::open_driver_connection(driver, client_socket_path, server_socket_path)){
        return 1;
    }

    //Register signals for "proper" shutdown
    signal(SIGTERM, terminate);
    signal(SIGINT, terminate);

    // Register the source and sensors
    source_id = asgard::register_source(driver, "ir");
    button_actuator_id = asgard::register_actuator(driver, source_id, "ir_button_1");

    //Read the default LIRC config
    struct lirc_config* config;
    if(lirc_readconfig(NULL,&config,NULL)==0){
        char* code;

        //Do stuff while LIRC socket is open  0=open  -1=closed.
        while(lirc_nextcode(&code)==0){
            //If code = NULL, nothing was returned from LIRC socket
            if(code){
                //Send code further
                ir_received(code);

                //Need to free up code before the next loop
                free(code);
            }
        }

        //Frees the data structures associated with config.
        lirc_freeconfig(config);
    } else {
        std::cout << "asgard:ir: Failed to read LIRC config" << std::endl;
    }

    stop();

    return 0;
}
<commit_msg>Use PI configuration file<commit_after>//=======================================================================
// Copyright (c) 2015-2016 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#include "asgard/driver.hpp"

extern "C" {
#include <lirc/lirc_client.h>
}

namespace {

std::vector<asgard::KeyValue> config;
asgard::driver_connector driver;

// The remote IDs
int source_id = -1;
int button_actuator_id = -1;

void stop(){
    std::cout << "asgard:ir: stop the driver" << std::endl;

    //Closes LIRC
    lirc_deinit();

    asgard::unregister_actuator(driver, source_id, button_actuator_id);
    asgard::unregister_source(driver, source_id);

    // Unlink the client socket
    unlink(asgard::get_string_value(config, "ir_client_socket_path"));

    // Close the socket
    close(driver.socket_fd);
}

void terminate(int){
    stop();

    std::exit(0);
}

void ir_received(char* raw_code){
    std::string full_code(raw_code);

    auto code_end = full_code.find(' ');
    std::string code(full_code.begin(), full_code.begin() + code_end);

    auto repeat_end = full_code.find(' ', code_end + 1);
    std::string repeat(full_code.begin() + code_end + 1, full_code.begin() + repeat_end);

    auto key_end = full_code.find(' ', repeat_end + 1);
    std::string key(full_code.begin() + repeat_end + 1, full_code.begin() + key_end);

    std::cout << "asgard:ir: Received: " << code << ":" << repeat << ":" << key << std::endl;

    asgard::send_event(driver, source_id, button_actuator_id, key);
}

} //End of anonymous namespace

int main(){
    //Initiate LIRC. Exit on failure
    char lirc_name[] = "lirc";
    if(lirc_init(lirc_name, 1) == -1){
        std::cout << "asgard:ir: Failed to init LIRC" << std::endl;
        return 1;
    }

    load_config(config);

    // Open the connection
    if(!asgard::open_driver_connection(driver, asgard::get_string_value(config, "ir_client_socket_path"), asgard::get_string_value(config, "server_socket_path"))){
        return 1;
    }

    //Register signals for "proper" shutdown
    signal(SIGTERM, terminate);
    signal(SIGINT, terminate);

    // Register the source and sensors
    source_id = asgard::register_source(driver, "ir");
    button_actuator_id = asgard::register_actuator(driver, source_id, "ir_button_1");

    //Read the default LIRC config
    struct lirc_config* config;
    if(lirc_readconfig(NULL,&config,NULL)==0){
        char* code;

        //Do stuff while LIRC socket is open  0=open  -1=closed.
        while(lirc_nextcode(&code)==0){
            //If code = NULL, nothing was returned from LIRC socket
            if(code){
                //Send code further
                ir_received(code);

                //Need to free up code before the next loop
                free(code);
            }
        }

        //Frees the data structures associated with config.
        lirc_freeconfig(config);
    } else {
        std::cout << "asgard:ir: Failed to read LIRC config" << std::endl;
    }

    stop();

    return 0;
}
<|endoftext|>


<commit_before>// Copyright 2010-2012 RethinkDB, all rights reserved.
#include "concurrency/watchable.hpp"

#include <functional>

#include "errors.hpp"
#include <boost/bind.hpp>
#include <boost/shared_ptr.hpp>

#include "concurrency/cond_var.hpp"
#include "concurrency/wait_any.hpp"

template <class result_type, class outer_type, class callable_type>
class subview_watchable_t : public watchable_t<result_type> {
public:
    subview_watchable_t(const callable_type &l, watchable_t<outer_type> *p) :
        cache(new lensed_value_cache_t(l, p)) { }

    subview_watchable_t *clone() const {
        return new subview_watchable_t(cache);
    }

    result_type get() {
        return *cache->get();
    }

    virtual void apply_read(const std::function<void(const result_type*)> &read) {
        ASSERT_NO_CORO_WAITING;
        read(cache->get());
    }

    publisher_t<boost::function<void()> > *get_publisher() {
        return cache->get_publisher();
    }

    rwi_lock_assertion_t *get_rwi_lock_assertion() {
        return cache->parent->get_rwi_lock_assertion();
    }

private:
    // TODO (daniel): Document how incremental lenses work.
    class lensed_value_cache_t : public home_thread_mixin_t {
    public:
        lensed_value_cache_t(const callable_type &l, watchable_t<outer_type> *p) :
            parent(p->clone()),
            lens(l),
            parent_subscription(boost::bind(
                &subview_watchable_t<result_type, outer_type, callable_type>::lensed_value_cache_t::on_parent_changed,
                this), parent->get_publisher()) {

            compute_value();
        }

        ~lensed_value_cache_t() {
            assert_thread();
        }

        const result_type *get() {
            assert_thread();
            return &cached_value;
        }

        publisher_t<boost::function<void()> > *get_publisher() {
            assert_thread();
            return publisher_controller.get_publisher();
        }

        clone_ptr_t<watchable_t<outer_type> > parent;

    private:
        bool compute_value() {
            // The closure is to avoid copying the whole value from the parent.

            bool value_changed = false;
            /* C++11: auto op = [&] (const outer_type *val) -> void { ... }
            Because we cannot use C++11 lambdas yet due to missing support in
            GCC 4.4, this is the messy work-around: */
            struct op_closure_t {
                void operator()(const outer_type *val) {
                    value_changed = lens(*val, &cached_value);
                }
                op_closure_t(callable_type &c1, bool &c2, result_type &c3) :
                    lens(c1),
                    value_changed(c2),
                    cached_value(c3) {
                }
                callable_type &lens;
                bool &value_changed;
                result_type &cached_value;
            };
            op_closure_t op(lens, value_changed, cached_value);

            parent->apply_read(std::bind(&op_closure_t::operator(), &op, std::placeholders::_1));

            return value_changed;
        }

        void on_parent_changed() {
            assert_thread();
            const bool value_changed = compute_value();
            if (value_changed) {
                publisher_controller.publish(&call_function);
            }
        }

        callable_type lens;
        result_type cached_value;
        publisher_controller_t<boost::function<void()> > publisher_controller;
        publisher_t<boost::function<void()> >::subscription_t parent_subscription;
    };

    subview_watchable_t(const boost::shared_ptr<lensed_value_cache_t> &_cache) :
        cache(_cache) { }

    boost::shared_ptr<lensed_value_cache_t> cache;
};

// TODO! Document
template<class outer_type, class callable_type>
class non_incremental_lens_wrapper_t {
public:
    typedef typename boost::result_of<callable_type(outer_type)>::type result_type;

    explicit non_incremental_lens_wrapper_t(const callable_type &_inner) :
        inner(_inner) {
    }

    bool operator()(const outer_type &input, result_type *current_out) {
        guarantee(current_out != NULL);
        result_type old_value = *current_out;
        *current_out = inner(input);
        return old_value != *current_out;
    }
private:
    callable_type inner;
};

template<class value_type>
template<class callable_type>
clone_ptr_t<watchable_t<typename callable_type::result_type> > watchable_t<value_type>::incremental_subview(const callable_type &lens) {
    assert_thread();
    return clone_ptr_t<watchable_t<typename callable_type::result_type> >(
        new subview_watchable_t<typename callable_type::result_type, value_type, callable_type>(lens, this));
}

template<class value_type>
template<class result_type, class callable_type>
clone_ptr_t<watchable_t<result_type> > watchable_t<value_type>::incremental_subview(const callable_type &lens) {
    assert_thread();
    return clone_ptr_t<watchable_t<result_type> >(
        new subview_watchable_t<result_type, value_type, callable_type>(lens, this));
}

template<class value_type>
template<class callable_type>
clone_ptr_t<watchable_t<typename boost::result_of<callable_type(value_type)>::type> > watchable_t<value_type>::subview(const callable_type &lens) {
    assert_thread();
    typedef non_incremental_lens_wrapper_t<value_type, callable_type> wrapped_callable_type;
    wrapped_callable_type wrapped_lens(lens);
    return clone_ptr_t<watchable_t<typename wrapped_callable_type::result_type> >(
        new subview_watchable_t<typename wrapped_callable_type::result_type, value_type, wrapped_callable_type>(wrapped_lens, this));
}

template<class value_type>
template<class callable_type>
void watchable_t<value_type>::run_until_satisfied(const callable_type &fun, signal_t *interruptor) THROWS_ONLY(interrupted_exc_t) {
    assert_thread();
    clone_ptr_t<watchable_t<value_type> > clone_this(this->clone());
    while (true) {
        cond_t changed;
        typename watchable_t<value_type>::subscription_t subs(boost::bind(&cond_t::pulse_if_not_already_pulsed, &changed));
        {
            typename watchable_t<value_type>::freeze_t freeze(clone_this);
            ASSERT_FINITE_CORO_WAITING;
            if (fun(clone_this->get())) {
                return;
            }
            subs.reset(clone_this, &freeze);
        }
        wait_interruptible(&changed, interruptor);
    }
}

template<class a_type, class b_type, class callable_type>
void run_until_satisfied_2(
        const clone_ptr_t<watchable_t<a_type> > &a,
        const clone_ptr_t<watchable_t<b_type> > &b,
        const callable_type &fun,
        signal_t *interruptor) THROWS_ONLY(interrupted_exc_t) {
    a->assert_thread();
    b->assert_thread();
    while (true) {
        cond_t changed;
        typename watchable_t<a_type>::subscription_t a_subs(boost::bind(&cond_t::pulse_if_not_already_pulsed, &changed));
        typename watchable_t<b_type>::subscription_t b_subs(boost::bind(&cond_t::pulse_if_not_already_pulsed, &changed));
        {
            typename watchable_t<a_type>::freeze_t a_freeze(a);
            typename watchable_t<b_type>::freeze_t b_freeze(b);
            ASSERT_FINITE_CORO_WAITING;
            if (fun(a->get(), b->get())) {
                return;
            }
            a_subs.reset(a, &a_freeze);
            b_subs.reset(b, &b_freeze);
        }
        wait_interruptible(&changed, interruptor);
    }
}
<commit_msg>Use watchable subscription_t together with a freeze_t in subview_watchable_t constructor.<commit_after>// Copyright 2010-2012 RethinkDB, all rights reserved.
#include "concurrency/watchable.hpp"

#include <functional>

#include "errors.hpp"
#include <boost/bind.hpp>
#include <boost/shared_ptr.hpp>

#include "concurrency/cond_var.hpp"
#include "concurrency/wait_any.hpp"

template <class result_type, class outer_type, class callable_type>
class subview_watchable_t : public watchable_t<result_type> {
public:
    subview_watchable_t(const callable_type &l, watchable_t<outer_type> *p) :
        cache(new lensed_value_cache_t(l, p)) { }

    subview_watchable_t *clone() const {
        return new subview_watchable_t(cache);
    }

    result_type get() {
        return *cache->get();
    }

    virtual void apply_read(const std::function<void(const result_type*)> &read) {
        ASSERT_NO_CORO_WAITING;
        read(cache->get());
    }

    publisher_t<boost::function<void()> > *get_publisher() {
        return cache->get_publisher();
    }

    rwi_lock_assertion_t *get_rwi_lock_assertion() {
        return cache->parent->get_rwi_lock_assertion();
    }

private:
    // TODO (daniel): Document how incremental lenses work.
    class lensed_value_cache_t : public home_thread_mixin_t {
    public:
        lensed_value_cache_t(const callable_type &l, watchable_t<outer_type> *p) :
            parent(p->clone()),
            lens(l),
            parent_subscription(boost::bind(
                &subview_watchable_t<result_type, outer_type, callable_type>::lensed_value_cache_t::on_parent_changed,
                this)) {
            typename watchable_t<outer_type>::freeze_t freeze(parent);
            ASSERT_FINITE_CORO_WAITING;
            compute_value();
            parent_subscription.reset(parent, &freeze);
        }

        ~lensed_value_cache_t() {
            assert_thread();
        }

        const result_type *get() {
            assert_thread();
            return &cached_value;
        }

        publisher_t<boost::function<void()> > *get_publisher() {
            assert_thread();
            return publisher_controller.get_publisher();
        }

        clone_ptr_t<watchable_t<outer_type> > parent;

    private:
        bool compute_value() {
            // The closure is to avoid copying the whole value from the parent.

            bool value_changed = false;
            /* C++11: auto op = [&] (const outer_type *val) -> void { ... }
            Because we cannot use C++11 lambdas yet due to missing support in
            GCC 4.4, this is the messy work-around: */
            struct op_closure_t {
                void operator()(const outer_type *val) {
                    value_changed = lens(*val, &cached_value);
                }
                op_closure_t(callable_type &c1, bool &c2, result_type &c3) :
                    lens(c1),
                    value_changed(c2),
                    cached_value(c3) {
                }
                callable_type &lens;
                bool &value_changed;
                result_type &cached_value;
            };
            op_closure_t op(lens, value_changed, cached_value);

            parent->apply_read(std::bind(&op_closure_t::operator(), &op, std::placeholders::_1));

            return value_changed;
        }

        void on_parent_changed() {
            assert_thread();
            const bool value_changed = compute_value();
            if (value_changed) {
                publisher_controller.publish(&call_function);
            }
        }

        callable_type lens;
        result_type cached_value;
        publisher_controller_t<boost::function<void()> > publisher_controller;
        typename watchable_t<outer_type>::subscription_t parent_subscription;
    };

    subview_watchable_t(const boost::shared_ptr<lensed_value_cache_t> &_cache) :
        cache(_cache) { }

    boost::shared_ptr<lensed_value_cache_t> cache;
};

// TODO! Document
template<class outer_type, class callable_type>
class non_incremental_lens_wrapper_t {
public:
    typedef typename boost::result_of<callable_type(outer_type)>::type result_type;

    explicit non_incremental_lens_wrapper_t(const callable_type &_inner) :
        inner(_inner) {
    }

    bool operator()(const outer_type &input, result_type *current_out) {
        guarantee(current_out != NULL);
        result_type old_value = *current_out;
        *current_out = inner(input);
        return old_value != *current_out;
    }
private:
    callable_type inner;
};

template<class value_type>
template<class callable_type>
clone_ptr_t<watchable_t<typename callable_type::result_type> > watchable_t<value_type>::incremental_subview(const callable_type &lens) {
    assert_thread();
    return clone_ptr_t<watchable_t<typename callable_type::result_type> >(
        new subview_watchable_t<typename callable_type::result_type, value_type, callable_type>(lens, this));
}

template<class value_type>
template<class result_type, class callable_type>
clone_ptr_t<watchable_t<result_type> > watchable_t<value_type>::incremental_subview(const callable_type &lens) {
    assert_thread();
    return clone_ptr_t<watchable_t<result_type> >(
        new subview_watchable_t<result_type, value_type, callable_type>(lens, this));
}

template<class value_type>
template<class callable_type>
clone_ptr_t<watchable_t<typename boost::result_of<callable_type(value_type)>::type> > watchable_t<value_type>::subview(const callable_type &lens) {
    assert_thread();
    typedef non_incremental_lens_wrapper_t<value_type, callable_type> wrapped_callable_type;
    wrapped_callable_type wrapped_lens(lens);
    return clone_ptr_t<watchable_t<typename wrapped_callable_type::result_type> >(
        new subview_watchable_t<typename wrapped_callable_type::result_type, value_type, wrapped_callable_type>(wrapped_lens, this));
}

template<class value_type>
template<class callable_type>
void watchable_t<value_type>::run_until_satisfied(const callable_type &fun, signal_t *interruptor) THROWS_ONLY(interrupted_exc_t) {
    assert_thread();
    clone_ptr_t<watchable_t<value_type> > clone_this(this->clone());
    while (true) {
        cond_t changed;
        typename watchable_t<value_type>::subscription_t subs(boost::bind(&cond_t::pulse_if_not_already_pulsed, &changed));
        {
            typename watchable_t<value_type>::freeze_t freeze(clone_this);
            ASSERT_FINITE_CORO_WAITING;
            if (fun(clone_this->get())) {
                return;
            }
            subs.reset(clone_this, &freeze);
        }
        wait_interruptible(&changed, interruptor);
    }
}

template<class a_type, class b_type, class callable_type>
void run_until_satisfied_2(
        const clone_ptr_t<watchable_t<a_type> > &a,
        const clone_ptr_t<watchable_t<b_type> > &b,
        const callable_type &fun,
        signal_t *interruptor) THROWS_ONLY(interrupted_exc_t) {
    a->assert_thread();
    b->assert_thread();
    while (true) {
        cond_t changed;
        typename watchable_t<a_type>::subscription_t a_subs(boost::bind(&cond_t::pulse_if_not_already_pulsed, &changed));
        typename watchable_t<b_type>::subscription_t b_subs(boost::bind(&cond_t::pulse_if_not_already_pulsed, &changed));
        {
            typename watchable_t<a_type>::freeze_t a_freeze(a);
            typename watchable_t<b_type>::freeze_t b_freeze(b);
            ASSERT_FINITE_CORO_WAITING;
            if (fun(a->get(), b->get())) {
                return;
            }
            a_subs.reset(a, &a_freeze);
            b_subs.reset(b, &b_freeze);
        }
        wait_interruptible(&changed, interruptor);
    }
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: cacheoptions.hxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-08 09:11:42 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    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., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef INCLUDED_SVTOOLS_CACHEOPTIONS_HXX
#define INCLUDED_SVTOOLS_CACHEOPTIONS_HXX

//_________________________________________________________________________________________________________________
//  includes
//_________________________________________________________________________________________________________________

#ifndef INCLUDED_SVLDLLAPI_H
#include "svtools/svldllapi.h"
#endif

#ifndef _SAL_TYPES_H_
#include <sal/types.h>
#endif
#ifndef _OSL_MUTEX_HXX_
#include <osl/mutex.hxx>
#endif
#ifndef _RTL_USTRING_
#include <rtl/ustring>
#endif

//_________________________________________________________________________________________________________________
//  forward declarations
//_________________________________________________________________________________________________________________

/*-************************************************************************************************************//**
    @short          forward declaration to our private date container implementation
    @descr          We use these class as internal member to support small memory requirements.
                    You can create the container if it is neccessary. The class which use these mechanism
                    is faster and smaller then a complete implementation!
*//*-*************************************************************************************************************/

class SvtCacheOptions_Impl;

//_________________________________________________________________________________________________________________
//  declarations
//_________________________________________________________________________________________________________________

/*-************************************************************************************************************//**
    @short          collect informations about startup features
    @descr          -

    @implements     -
    @base           -

    @devstatus      ready to use
*//*-*************************************************************************************************************/

class SVL_DLLPUBLIC SvtCacheOptions
{
    //-------------------------------------------------------------------------------------------------------------
    //  public methods
    //-------------------------------------------------------------------------------------------------------------

    public:

        //---------------------------------------------------------------------------------------------------------
        //  constructor / destructor
        //---------------------------------------------------------------------------------------------------------

        /*-****************************************************************************************************//**
            @short      standard constructor and destructor
            @descr      This will initialize an instance with default values.
                        We implement these class with a refcount mechanism! Every instance of this class increase it
                        at create and decrease it at delete time - but all instances use the same data container!
                        He is implemented as a static member ...

            @seealso    member m_nRefCount
            @seealso    member m_pDataContainer

            @param      -
            @return     -

            @onerror    -
        *//*-*****************************************************************************************************/

         SvtCacheOptions();
        ~SvtCacheOptions();

        //---------------------------------------------------------------------------------------------------------
        //  interface
        //---------------------------------------------------------------------------------------------------------

        /*-****************************************************************************************************//**
            @short      interface methods to get and set value of config key "org.openoffice.Office.Common/_3D-Engine/..."
            @descr      These options describe internal states to enable/disable features of installed office.

                        GetWriterOLE_Objects()
                        SetWriterOLE_Objects()              =>  set the number of Writer OLE objects to be cached

                        GetDrawingEngineOLE_Objects()
                        SetDrawingEngineOLE_Objects()       =>  set the number of DrawingEngine OLE objects to be cached

                        GetGraphicManagerTotalCacheSize()
                        SetGraphicManagerTotalCacheSize()   =>  set the maximum cache size used by GraphicManager to cache graphic objects

                        GetGraphicManagerObjectCacheSize()
                        SetGraphicManagerObjectCacheSize()  =>  set the maximum cache size for one GraphicObject to be cached by GraphicManager

            @seealso    configuration package "org.openoffice.Office.Common/_3D-Engine"
        *//*-*****************************************************************************************************/

        sal_Int32   GetWriterOLE_Objects() const;
        sal_Int32   GetDrawingEngineOLE_Objects() const;
        sal_Int32   GetGraphicManagerTotalCacheSize() const;
        sal_Int32   GetGraphicManagerObjectCacheSize() const;
        sal_Int32   GetGraphicManagerObjectReleaseTime() const;

        void        SetWriterOLE_Objects( sal_Int32 nObjects );
        void        SetDrawingEngineOLE_Objects( sal_Int32 nObjects );
        void        SetGraphicManagerTotalCacheSize( sal_Int32 nTotalCacheSize );
        void        SetGraphicManagerObjectCacheSize( sal_Int32 nObjectCacheSize );
        void        SetGraphicManagerObjectReleaseTime( sal_Int32 nReleaseTimeSeconds );

    //-------------------------------------------------------------------------------------------------------------
    //  private methods
    //-------------------------------------------------------------------------------------------------------------

    private:

        /*-****************************************************************************************************//**
            @short      return a reference to a static mutex
            @descr      These class use his own static mutex to be threadsafe.
                        We create a static mutex only for one ime and use at different times.

            @seealso    -

            @param      -
            @return     A reference to a static mutex member.

            @onerror    -
        *//*-*****************************************************************************************************/

        SVL_DLLPRIVATE static ::osl::Mutex& GetOwnStaticMutex();

    //-------------------------------------------------------------------------------------------------------------
    //  private member
    //-------------------------------------------------------------------------------------------------------------

    private:

        /*Attention

            Don't initialize these static member in these header!
            a) Double dfined symbols will be detected ...
            b) and unresolved externals exist at linking time.
            Do it in your source only.
         */

        static SvtCacheOptions_Impl*    m_pDataContainer    ;   /// impl. data container as dynamic pointer for smaller memory requirements!
        static sal_Int32                m_nRefCount         ;   /// internal ref count mechanism

};      // class SvtOptions3D

#endif // #ifndef INCLUDED_SVTOOLS_CACHEOPTIONS_HXX
<commit_msg>INTEGRATION: CWS warnings01 (1.4.62); FILE MERGED 2005/10/25 12:43:51 pl 1.4.62.1: #i55991# removed warnings for linux platform<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: cacheoptions.hxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: hr $ $Date: 2006-06-19 20:11:10 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    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., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef INCLUDED_SVTOOLS_CACHEOPTIONS_HXX
#define INCLUDED_SVTOOLS_CACHEOPTIONS_HXX

//_________________________________________________________________________________________________________________
//  includes
//_________________________________________________________________________________________________________________

#ifndef INCLUDED_SVLDLLAPI_H
#include "svtools/svldllapi.h"
#endif

#ifndef _SAL_TYPES_H_
#include <sal/types.h>
#endif
#ifndef _OSL_MUTEX_HXX_
#include <osl/mutex.hxx>
#endif
#ifndef _RTL_USTRING_HXX_
#include <rtl/ustring.hxx>
#endif

//_________________________________________________________________________________________________________________
//  forward declarations
//_________________________________________________________________________________________________________________

/*-************************************************************************************************************//**
    @short          forward declaration to our private date container implementation
    @descr          We use these class as internal member to support small memory requirements.
                    You can create the container if it is neccessary. The class which use these mechanism
                    is faster and smaller then a complete implementation!
*//*-*************************************************************************************************************/

class SvtCacheOptions_Impl;

//_________________________________________________________________________________________________________________
//  declarations
//_________________________________________________________________________________________________________________

/*-************************************************************************************************************//**
    @short          collect informations about startup features
    @descr          -

    @implements     -
    @base           -

    @devstatus      ready to use
*//*-*************************************************************************************************************/

class SVL_DLLPUBLIC SvtCacheOptions
{
    //-------------------------------------------------------------------------------------------------------------
    //  public methods
    //-------------------------------------------------------------------------------------------------------------

    public:

        //---------------------------------------------------------------------------------------------------------
        //  constructor / destructor
        //---------------------------------------------------------------------------------------------------------

        /*-****************************************************************************************************//**
            @short      standard constructor and destructor
            @descr      This will initialize an instance with default values.
                        We implement these class with a refcount mechanism! Every instance of this class increase it
                        at create and decrease it at delete time - but all instances use the same data container!
                        He is implemented as a static member ...

            @seealso    member m_nRefCount
            @seealso    member m_pDataContainer

            @param      -
            @return     -

            @onerror    -
        *//*-*****************************************************************************************************/

         SvtCacheOptions();
        ~SvtCacheOptions();

        //---------------------------------------------------------------------------------------------------------
        //  interface
        //---------------------------------------------------------------------------------------------------------

        /*-****************************************************************************************************//**
            @short      interface methods to get and set value of config key "org.openoffice.Office.Common/_3D-Engine/..."
            @descr      These options describe internal states to enable/disable features of installed office.

                        GetWriterOLE_Objects()
                        SetWriterOLE_Objects()              =>  set the number of Writer OLE objects to be cached

                        GetDrawingEngineOLE_Objects()
                        SetDrawingEngineOLE_Objects()       =>  set the number of DrawingEngine OLE objects to be cached

                        GetGraphicManagerTotalCacheSize()
                        SetGraphicManagerTotalCacheSize()   =>  set the maximum cache size used by GraphicManager to cache graphic objects

                        GetGraphicManagerObjectCacheSize()
                        SetGraphicManagerObjectCacheSize()  =>  set the maximum cache size for one GraphicObject to be cached by GraphicManager

            @seealso    configuration package "org.openoffice.Office.Common/_3D-Engine"
        *//*-*****************************************************************************************************/

        sal_Int32   GetWriterOLE_Objects() const;
        sal_Int32   GetDrawingEngineOLE_Objects() const;
        sal_Int32   GetGraphicManagerTotalCacheSize() const;
        sal_Int32   GetGraphicManagerObjectCacheSize() const;
        sal_Int32   GetGraphicManagerObjectReleaseTime() const;

        void        SetWriterOLE_Objects( sal_Int32 nObjects );
        void        SetDrawingEngineOLE_Objects( sal_Int32 nObjects );
        void        SetGraphicManagerTotalCacheSize( sal_Int32 nTotalCacheSize );
        void        SetGraphicManagerObjectCacheSize( sal_Int32 nObjectCacheSize );
        void        SetGraphicManagerObjectReleaseTime( sal_Int32 nReleaseTimeSeconds );

    //-------------------------------------------------------------------------------------------------------------
    //  private methods
    //-------------------------------------------------------------------------------------------------------------

    private:

        /*-****************************************************************************************************//**
            @short      return a reference to a static mutex
            @descr      These class use his own static mutex to be threadsafe.
                        We create a static mutex only for one ime and use at different times.

            @seealso    -

            @param      -
            @return     A reference to a static mutex member.

            @onerror    -
        *//*-*****************************************************************************************************/

        SVL_DLLPRIVATE static ::osl::Mutex& GetOwnStaticMutex();

    //-------------------------------------------------------------------------------------------------------------
    //  private member
    //-------------------------------------------------------------------------------------------------------------

    private:

        /*Attention

            Don't initialize these static member in these header!
            a) Double dfined symbols will be detected ...
            b) and unresolved externals exist at linking time.
            Do it in your source only.
         */

        static SvtCacheOptions_Impl*    m_pDataContainer    ;   /// impl. data container as dynamic pointer for smaller memory requirements!
        static sal_Int32                m_nRefCount         ;   /// internal ref count mechanism

};      // class SvtOptions3D

#endif // #ifndef INCLUDED_SVTOOLS_CACHEOPTIONS_HXX
<|endoftext|>