<commit_before>#include "ns3/core-module.h"
#include "ns3/network-module.h"
#include "ns3/csma-module.h"
#include "ns3/internet-module.h"
#include "ns3/applications-module.h"
#include "ns3/ipv4-global-routing-helper.h"

using namespace ns3;

/*
			Example Topology: 2 levels, each node connected to 2 leaves per level.

                                Client
                            +------------+
                            |    Root    |
                            +------------+
                            /            \
                           /              \
                +-------------+           +-------------+
                | leftRouther |           | rightRouter |
                +-------------+	          +-------------+
                  /        \                  /       \
                 /          \                /         \
            +----+       +----+            +----+       +----+
            | n1 |       | n2 |            | n3 |       | n4 |
            +----+       +----+            +----+       +----+
            Server       Server            Server       Server
 */

/**
 *  Function to generate network topology as shown above, with an arbitrary number of
 *  levels or leave nodes. This function is recursive.
 *
 *  Ptr<Node> parent is the node to the network topology, it is equivalent to the motherNode
 *  illustrated above
 *
 *  int numLeaves is the number of leaves each parent node should be connected with.
 *  Ipv4InterfaceContainer* ipInterfaces is a variable to keep track of the server nodes addresses
 *  (explained more in the main function)
 *
 *  int level is the level of the network topology, level = 1 would be a parent node connected with
 *  numLeaves
 */
void networkTree(Ptr<Node> parent, int numLeaves, Ipv4InterfaceContainer* ipInterfaces, int level);

/**
 *  Function to install a UDP server application on each server node that echo's back the
 *  packet it receives.
 *
 *  NodeContainer* leaves is a reference to the nodes to install the server application onto.
 *
 *  int port is the port number which all server nodes listen to.
 *
 *  float start, end is the start and end of the application
 */
void installUdpEchoServers(NodeContainer* leaves, int port, float start, float end);

/**
 *  Function to install several UDP client applications to send to all the server nodes
 *  and expect a echo packet reply
 *
 *  Ptr<Node> node, node to intall the several UDP client apps onto
 *
 *  int port is the port number the server nodes are supposed to listen to
 *
 *  Ipv4InterfaceContainer* ipInterfaces is the variable that contains all the addresses
 *  of the server nodes, and is used for the client app to send a packet to them
 *
 *  float start, end is the start and end of the application
 */
void installUdpEchoClient(Ptr<Node> node, int port, Ipv4InterfaceContainer* ipInterfaces,
                          float start, float end);

// Since this code uses recursion, using a global variable to specify a branch was useful
static int branch = 1;

NS_LOG_COMPONENT_DEFINE ("networkTree"); // Naming this script to enable logging (debugging)

int main (int argc, char *argv[])
{
  LogComponentEnable ("networkTree", LOG_LEVEL_INFO); // Enable logging or debugging at the info level

  NS_LOG_INFO ("Testing"); // Code reached here, should output "testing" on the shell

  // We need to log packet info of client node, which contains a UDP application
  LogComponentEnable ("UdpEchoClientApplication", LOG_LEVEL_INFO);

  // uncomment line below to log server applications listening to packets and echoing them back
  //LogComponentEnable ("UdpEchoServerApplication", LOG_LEVEL_INFO);

  // There is a lot of congestion in this network topology, we need to increase the buffer size,
  // otherwise packets will be dropped, we need to do this at the IP layer and the link layer,
  // below increases buffer size to 1000 at the IP layer, as in, 1000 packets can be queued up
  Config::SetDefault("ns3::ArpCache::PendingQueueSize", UintegerValue(1000));

  Ptr<Node> client = CreateObject<Node> ();

  InternetStackHelper stack;
  stack.Install (client);

  // We need to keep track of the IP addresses of the server nodes for the client to send
  // packets to them, this can be done using a Ipv4InterfaceContainer var. The var ipInterfaces
  // will be used to contain all the IP addresses of the server nodes.
  Ipv4InterfaceContainer ipInterfaces;

  // Generate the topology with connections and IPv4 addresses
  // here, each node has 3 leaves, and it is 2 levels long, so there should be 3*2 = 6 server nodes
  // at the bottom, modify them to create the appropriate topology
  networkTree(client, 3, &ipInterfaces, 2);

  // Install the UDP application on the client node and have these applications send a packet to
  // all the server nodes
  installUdpEchoClient(client, 9, &ipInterfaces, 2.0, 2000.0);

  // Since this is dynamic routing and with a large network topology, populating the routing tables
  // can take quite a long time. To simulate topology with 2 levels and 32 leaves at each level,
  // there would be 32*32 = 1024 server nodes, it takes about 30 minutes to populate the tables.
  NS_LOG_INFO ("Populating table");
  Ipv4GlobalRoutingHelper::PopulateRoutingTables ();
  NS_LOG_INFO ("Populating table done");

  Simulator::Stop (Seconds (200));
  NS_LOG_INFO ("Simulation begins now");
  Simulator::Run ();
  NS_LOG_INFO ("Simulation ends");
  Simulator::Destroy ();
  return 0;
}

void networkTree(Ptr<Node> parent, int numLeaves, Ipv4InterfaceContainer* ipInterfaces, int level) {
  if (level > 0) { // Base case, only recursively create more connections if level > 0
    // Create the nodes to be connected as leaves
    NodeContainer leaves;
    leaves.Create(numLeaves);

    // Create the net devices on the nodes and a network channel connecting them
    // according to the topology
    // Create the variable to help create the net devices and connect nodes to channels
    CsmaHelper csma;
    // Increase the buffer size at the link layer
    csma.SetQueue ("ns3::DropTailQueue", "MaxPackets", UintegerValue(1000));
    // Set the typical Data Centre standard values
    csma.SetChannelAttribute ("DataRate", StringValue ("1Gbps"));
    csma.SetChannelAttribute ("Delay", StringValue ("1ms"));

    // Connect the parent node to its leave nodes
    std::vector<NetDeviceContainer> netC; // save them to assign IP addresses
    for (int leaf = 0; leaf < leaves.GetN(); leaf++) {
      netC.push_back( csma.Install( NodeContainer( parent, leaves.Get(leaf) ) ) );
    }

    // Set up the IP addresses to the leaves
    InternetStackHelper stack;
    stack.Install (leaves);
    // Make sure level == 1 to ensure server nodes are installed at the bottom of the topology
    if (level == 1) installUdpEchoServers(&leaves, 9, 1.0, 2000.0);

    // Assign IP addresses to the leaves
    char buffer [15];
    Ipv4AddressHelper address;
    for (int netDev = 0; netDev < netC.size(); netDev++) {
      // Specify the address using string formating
      sprintf (buffer, "%d.%d.%d.0", 9 + level, branch, netDev + 1);
      address.SetBase (buffer, "255.255.255.0");
      Ipv4InterfaceContainer tempContainer = address.Assign( netC.at(netDev) );

      // Make sure we only obtain the addresses of the leaves nodes at the bottom of the topology
      if (level == 1) ipInterfaces->Add(tempContainer);

      // Recursion, connect each leaf to more nodes
      int leaf = netDev;
      networkTree(leaves.Get(leaf), numLeaves, ipInterfaces, level - 1);
    }
    branch++; // next branch in topology
  }
}

void installUdpEchoServers(NodeContainer* leaves, int port, float start, float end) {
  for (int leaf = 0; leaf < leaves->GetN(); leaf++) {
    Ptr<UdpEchoServer> serverApp = CreateObject<UdpEchoServer>();
    serverApp->SetAttribute("Port", UintegerValue(port)); // server apps listen to this port

    leaves->Get(leaf)->AddApplication(serverApp);

    serverApp->SetStartTime (Seconds (start));
    serverApp->SetStopTime (Seconds (end));
  }
}

void installUdpEchoClient(Ptr<Node> node, int port, Ipv4InterfaceContainer* ipInterfaces,
                          float start, float end) {
  // ipInterfaces contains the address of the net device of the server node and the
  // address of the net device connected to the server node (parent node).
  // In order to obtain only the server node addresses, the first address is parent
  // second is server, so start with ip = 1, and incumbent twice to obtain only server addresses
  for (int ip = 1; ip < ipInterfaces->GetN(); ip+=2) {
    Ptr<UdpEchoClient> echoClient = CreateObject<UdpEchoClient>();

    echoClient->SetRemote(ipInterfaces->GetAddress(ip), port);

    echoClient->SetAttribute ("MaxPackets", UintegerValue (1)); // send only 1 packet
    echoClient->SetAttribute ("PacketSize", UintegerValue (1 << 10)); // 1 KB
    node->AddApplication(echoClient);
    // Start each application and have each send a packet with a delay of 100 micro seconds
    int delay = 10000; // in terms of seconds, so if delay = 1 ms, it is 1000, or 1000th of a second
    echoClient->SetStartTime (Seconds (start + (ip - 1.0)/(2*delay) )); // formula to create delay using ip
    echoClient->SetStopTime (Seconds (end));
  }
}<commit_msg>Rename to networkTree.cc<commit_after><|endoftext|>


<commit_before>// Copyright 2020 The Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//
//   Graphs (influence maximization, coverage function)
//
// Class that stores a graph (e.g. a social network)
// with special support for DBLP.

// Input format:
// For normal graphs we expect on edge per line. Each edge is expected to be two
// space separated integers.
// For DBLP, each line is expected to be an edge followed by the year.

#include "graph.h"

#include "absl/container/node_hash_map.h"
#include "absl/container/node_hash_set.h"

using std::vector;

Graph::Graph(const std::string& name) : name_(name) {
  // Technical comment: would prefer to make this constructor private,
  // but this breaks a crucial line in getGraph.

  // Update this part with the file name.
  static const absl::node_hash_map<std::string, std::string> name_to_filename =
      {{"amazon", "../datasets/amazon/graph-relabeled-big-amazon.txt"},
       {"enron", "../datasets/enron/Email-Enron.txt"},
       {"twitter", "../datasets/twitter/graph-relabel-twitter.txt"},
       {"dblp", "../datasets/dblp/dblp-graph.txt"},
       {"pokec", "../datasets/pokec/soc-pokec-relationships.txt"},
       {"friendster", "../datasets/friendster/friendster.txt"}};

  if (!name_to_filename.count(name_)) {
    Fail("unknown graph name");
  }
  const std::string& file_name = name_to_filename.at(name_);

  std::cerr << "reading graph from " << file_name << "..." << std::endl;
  std::ifstream input(file_name);
  if (!input) {
    Fail("graph file does not exist");
  }
  // renumber[x] = new number of x
  unordered_map<int64_t, int> renumber;
  numVertices_ = 0;
  numEdges_ = 0;
  const bool is_dblp = (name_ == "dblp");
  int64_t first_endpoint, second_endpoint;
  unordered_set<int> leftVertices, rightVertices;
  while (input >> first_endpoint >> second_endpoint) {
    if (!renumber.count(first_endpoint)) {
      renumber[first_endpoint] = numVertices_;
      ++numVertices_;
      neighbors_.push_back({});
    }
    leftVertices.insert(renumber[first_endpoint]);
    if (!renumber.count(second_endpoint)) {
      renumber[second_endpoint] = numVertices_;
      ++numVertices_;
      neighbors_.push_back({});
    }
    rightVertices.insert(renumber[second_endpoint]);
    numEdges_++;
    neighbors_[renumber[first_endpoint]].push_back(renumber[second_endpoint]);
    // Note: our graphs are directed.
    // But in some cases you may want to also add the reverse edge.

    if (is_dblp) {
      int year;
      input >> year;
      publicationDates_[renumber[first_endpoint]].insert(year);
    }
  }
  leftVertices_.assign(leftVertices.begin(), leftVertices.end());
  rightVertices_.assign(rightVertices.begin(), rightVertices.end());
  std::cerr << "read graph with " << numVertices_ << " vertices "
       << "and " << numEdges_ << " edges" << std::endl;
}

const vector<int>& Graph::GetCoverableVertices() const {
  return rightVertices_;
}

const vector<int>& Graph::GetUniverseVertices() const { return leftVertices_; }

const vector<int>& Graph::GetNeighbors(int vertex_i) const {
  return neighbors_[vertex_i];
}

const std::string& Graph::GetName() const { return name_; }
<commit_msg>Internal change<commit_after>// Copyright 2020 The Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//
//   Graphs (influence maximization, coverage function)
//
// Class that stores a graph (e.g. a social network)
// with special support for DBLP.

// Input format:
// For normal graphs we expect on edge per line. Each edge is expected to be two
// space separated integers.
// For DBLP, each line is expected to be an edge followed by the year.

#include "graph.h"

#include "absl/container/node_hash_map.h"
#include "absl/container/node_hash_set.h"

using std::unordered_set;
using std::vector;

Graph::Graph(const std::string& name) : name_(name) {
  // Technical comment: would prefer to make this constructor private,
  // but this breaks a crucial line in getGraph.

  // Update this part with the file name.
  static const  unordered_map<std::string, std::string> name_to_filename =
      {{"amazon", "../datasets/amazon/graph-relabeled-big-amazon.txt"},
       {"enron", "../datasets/enron/Email-Enron.txt"},
       {"twitter", "../datasets/twitter/graph-relabel-twitter.txt"},
       {"dblp", "../datasets/dblp/dblp-graph.txt"},
       {"pokec", "../datasets/pokec/soc-pokec-relationships.txt"},
       {"friendster", "../datasets/friendster/friendster.txt"}};

  if (!name_to_filename.count(name_)) {
    Fail("unknown graph name");
  }
  const std::string& file_name = name_to_filename.at(name_);

  std::cerr << "reading graph from " << file_name << "..." << std::endl;
  std::ifstream input(file_name);
  if (!input) {
    Fail("graph file does not exist");
  }
  // renumber[x] = new number of x
  unordered_map<int64_t, int> renumber;
  numVertices_ = 0;
  numEdges_ = 0;
  const bool is_dblp = (name_ == "dblp");
  int64_t first_endpoint, second_endpoint;
  absl::node_hash_set<int> leftVertices, rightVertices;
  while (input >> first_endpoint >> second_endpoint) {
    if (!renumber.count(first_endpoint)) {
      renumber[first_endpoint] = numVertices_;
      ++numVertices_;
      neighbors_.push_back({});
    }
    leftVertices.insert(renumber[first_endpoint]);
    if (!renumber.count(second_endpoint)) {
      renumber[second_endpoint] = numVertices_;
      ++numVertices_;
      neighbors_.push_back({});
    }
    rightVertices.insert(renumber[second_endpoint]);
    numEdges_++;
    neighbors_[renumber[first_endpoint]].push_back(renumber[second_endpoint]);
    // Note: our graphs are directed.
    // But in some cases you may want to also add the reverse edge.

    if (is_dblp) {
      int year;
      input >> year;
      publicationDates_[renumber[first_endpoint]].insert(year);
    }
  }
  leftVertices_.assign(leftVertices.begin(), leftVertices.end());
  rightVertices_.assign(rightVertices.begin(), rightVertices.end());
  std::cerr << "read graph with " << numVertices_ << " vertices "
       << "and " << numEdges_ << " edges" << std::endl;
}

const vector<int>& Graph::GetCoverableVertices() const {
  return rightVertices_;
}

const vector<int>& Graph::GetUniverseVertices() const { return leftVertices_; }

const vector<int>& Graph::GetNeighbors(int vertex_i) const {
  return neighbors_[vertex_i];
}

const std::string& Graph::GetName() const { return name_; }
<|endoftext|>


<commit_before>// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/path_service.h"
#include "base/process/launch.h"
#include "base/strings/string_util.h"
#include "testing/gtest/include/gtest/gtest.h"

base::FilePath GinShellPath() {
  base::FilePath dir;
  PathService::Get(base::DIR_EXE, &dir);
  return dir.AppendASCII("gin_shell");
}

base::FilePath HelloWorldPath() {
  base::FilePath path;
  PathService::Get(base::DIR_SOURCE_ROOT, &path);
  return path
    .AppendASCII("gin")
    .AppendASCII("shell")
    .AppendASCII("hello_world.js");
}

TEST(GinShellTest, HelloWorld) {
  CommandLine cmd(GinShellPath());
  cmd.AppendArgPath(HelloWorldPath());
  std::string output;
  ASSERT_TRUE(base::GetAppOutput(cmd, &output));
  base::TrimWhitespaceASCII(output, base::TRIM_ALL, &output);
  ASSERT_EQ("Hello World", output);
}
<commit_msg>Verify that gin_shell and hello_world.js exist.<commit_after>// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/command_line.h"
#include "base/file_util.h"
#include "base/path_service.h"
#include "base/process/launch.h"
#include "base/strings/string_util.h"
#include "testing/gtest/include/gtest/gtest.h"

base::FilePath GinShellPath() {
  base::FilePath dir;
  PathService::Get(base::DIR_EXE, &dir);
  return dir.AppendASCII("gin_shell");
}

base::FilePath HelloWorldPath() {
  base::FilePath path;
  PathService::Get(base::DIR_SOURCE_ROOT, &path);
  return path
    .AppendASCII("gin")
    .AppendASCII("shell")
    .AppendASCII("hello_world.js");
}

TEST(GinShellTest, HelloWorld) {
  base::FilePath gin_shell_path(GinShellPath());
  base::FilePath hello_world_path(HelloWorldPath());
  ASSERT_TRUE(base::PathExists(gin_shell_path));
  ASSERT_TRUE(base::PathExists(hello_world_path));

  CommandLine cmd(gin_shell_path);
  cmd.AppendArgPath(hello_world_path);
  std::string output;
  ASSERT_TRUE(base::GetAppOutput(cmd, &output));
  base::TrimWhitespaceASCII(output, base::TRIM_ALL, &output);
  ASSERT_EQ("Hello World", output);
}
<|endoftext|>


<commit_before>/******************************************************************************
 *
 * Module      :  HaskinoRuntimeScheduler
 * Copyright   :  (c) University of Kansas
 * License     :  BSD3
 * Stability   :  experimental
 *
 * Haskino Runtime Scheduler module
 *****************************************************************************/

#include <Arduino.h>
#include "HaskinoRuntime.h"

// Scheduling routines
static void reschedule();
static void switchTo(TCB *newTask);
static bool minWait(TCB *task);
static void reschedule();

static TCB *firstTask = NULL;
static TCB *runningTask = NULL;
static int taskCount = 0;
static SEMAPHORE_C semaphores[NUM_SEMAPHORES];

// Temp variables used for C/Assembly transfer
volatile uint32_t taskStack;
volatile uint32_t taskFunction;

// Macros to save and restore context
#define SAVE_TASK_CONTEXT()\
asm volatile (\
"push r0                \n\t"\
"in r0, __SREG__        \n\t"\
"cli                    \n\t"\
"push r0                \n\t"\
"push r1                \n\t"\
"clr r1                 \n\t"\
"push r2                \n\t"\
"push r3                \n\t"\
"push r4                \n\t"\
"push r5                \n\t"\
"push r6                \n\t"\
"push r7                \n\t"\
"push r8                \n\t"\
"push r9                \n\t"\
"push r10               \n\t"\
"push r11               \n\t"\
"push r12               \n\t"\
"push r13               \n\t"\
"push r14               \n\t"\
"push r15               \n\t"\
"push r16               \n\t"\
"push r17               \n\t"\
"push r18               \n\t"\
"push r19               \n\t"\
"push r20               \n\t"\
"push r21               \n\t"\
"push r22               \n\t"\
"push r23               \n\t"\
"push r24               \n\t"\
"push r25               \n\t"\
"push r26               \n\t"\
"push r27               \n\t"\
"push r28               \n\t"\
"push r29               \n\t"\
"push r30               \n\t"\
"push r31               \n\t"\
"in r26, __SP_L__       \n\t"\
"in r27, __SP_H__       \n\t"\
"sts taskStack+1, r27   \n\t"\
"sts taskStack, r26     \n\t"\
"sei                    \n\t" : :);

#define LOAD_TASK_CONTEXT()\
asm volatile (\
"cli                    \n\t"\
"out __SP_L__, %A0      \n\t"\
"out __SP_H__, %B0      \n\t"\
"pop r31                \n\t"\
"pop r30                \n\t"\
"pop r29                \n\t"\
"pop r28                \n\t"\
"pop r27                \n\t"\
"pop r26                \n\t"\
"pop r25                \n\t"\
"pop r24                \n\t"\
"pop r23                \n\t"\
"pop r22                \n\t"\
"pop r21                \n\t"\
"pop r20                \n\t"\
"pop r19                \n\t"\
"pop r18                \n\t"\
"pop r17                \n\t"\
"pop r16                \n\t"\
"pop r15                \n\t"\
"pop r14                \n\t"\
"pop r13                \n\t"\
"pop r12                \n\t"\
"pop r11                \n\t"\
"pop r10                \n\t"\
"pop r9                 \n\t"\
"pop r8                 \n\t"\
"pop r7                 \n\t"\
"pop r6                 \n\t"\
"pop r5                 \n\t"\
"pop r4                 \n\t"\
"pop r3                 \n\t"\
"pop r2                 \n\t"\
"pop r1                 \n\t"\
"pop r0                 \n\t"\
"sei                    \n\t"\
"out __SREG__, r0       \n\t"\
"pop r0                 \n\t": : "r" (taskStack))

#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
    #define INIT_TASK_STACK_FUNC()\
    asm volatile(\
    "out __SP_L__, %A0  \n\t"\
    "out __SP_H__, %B0  \n\t"\
    "mov r0, %A1        \n\t"\
    "push r0            \n\t"\
    "mov r0, %B1        \n\t"\
    "push r0            \n\t"\
    "mov r0, %C1        \n\t"\
    "push r0            \n\t" : : "r" (taskStack), "r" (taskFunction))
#else
    #define INIT_TASK_STACK_FUNC()\
    asm volatile(\
    "out __SP_L__, %A0  \n\t"\
    "out __SP_H__, %B0  \n\t"\
    "mov r0, %A1        \n\t"\
    "push r0            \n\t"\
    "mov r0, %B1        \n\t"\
    "push r0            \n\t" : : "r" (taskStack), "r" (taskFunction))
#endif

static TCB *findTask(int id)
    {
    TCB *task = firstTask;

    while (task != NULL)
        {
        if (id == task->id)
            return task;
        task = task->next;
        }
    return NULL;
    }

void delayMilliseconds(uint32_t ms)
    {
#if 1
    runningTask->millis = millis() + ms;
    reschedule();
#else
    delay(ms);
#endif
    }

void createTask(uint8_t tid, void *tcb, int stackSize, void (*task)())
    {
    TCB *newTask = (TCB *) tcb;

    if (findTask(tid) == NULL)
        {
        newTask->next = firstTask;
        firstTask = newTask;
        newTask->id = tid;
        newTask->stackSize = stackSize;
        newTask->millis = 0;
        newTask->ready = false;
        newTask->hasRan = false;
        newTask->entry = task;
        newTask->stackPointer =
            (uint16_t) &newTask->stack[stackSize-sizeof(unsigned long)];
        taskCount++;
        }
    }

void deleteTask(uint8_t tid)
    {
    TCB *task;

    if ((task = findTask(tid)) != NULL)
        {
        task->ready = false;
        if (task == runningTask)
            reschedule();
        }
    }

void scheduleTask(uint8_t tid, uint32_t tt)
    {
    TCB *task;

    if ((task = findTask(tid)) != NULL)
        {
        task->millis = millis() + tt;
        task->ready = true;
        }
    }

void scheduleReset()
    {
    TCB *task = firstTask;

    // Set all tasks except for running one to false
    while (task != NULL)
        {
        if (task != runningTask)
            task->ready = false;
        task = task->next;
        }
    }

void taskComplete()
    {
    runningTask->ready = false;
    reschedule();
    }

static void switchTo(TCB *newTask)
    {
    SAVE_TASK_CONTEXT();
    runningTask->stackPointer = taskStack;

    runningTask = newTask;
    if(!runningTask->hasRan)
        {
        runningTask->hasRan = true;
        taskStack = (uint32_t) runningTask->stackPointer;
        taskFunction = (uint32_t) runningTask->entry;
        INIT_TASK_STACK_FUNC();
        }
    else
        {
        taskStack = (uint32_t) runningTask->stackPointer;
        LOAD_TASK_CONTEXT();
        }
    asm("ret");
    }

void startScheduler()
    {
    TCB *task;

    task = findTask(255);
    runningTask = task;
    switchTo(task);
    }

static bool minWait(TCB *task)
    {
    uint32_t now = millis();
    uint32_t minTime = 0x80000000UL;
    TCB *currTask = task;
    TCB *minTask = NULL;

    // Find the task that is ready to run and has the shortest delay
    do  {
        if (currTask->ready)
            {
            uint32_t timeDiff = currTask->millis - now;

            if (timeDiff >= 0x80000000UL)
                timeDiff = 0;
            if (timeDiff < minTime)
                {
                minTime = timeDiff;
                minTask = currTask;
                }
            }

        if (currTask->next == NULL)
            currTask = firstTask;
        else
            currTask = currTask->next;

        } while (currTask != task);

    // If one was found, then delay until its delay would time out
    // and switch to that task.
    if (minTask)
        {
        delay(minTime);
        if (minTask != runningTask)
            switchTo(minTask);
        return false;
        }
    else
        {
        return true;
        }
    }

static void reschedule()
    {
    TCB *next = runningTask->next;

    if (next == NULL)
        next = firstTask;

    // Loop while no tasks are ready.
    // Start the search with the task after the current one, so that
    // if all tasks used delayMillis(0), they would proceed in a
    // round robin fashion.

    while (minWait(next))
        {
        delay(1);
        }
    }

// Semphore routines

void giveSem(uint8_t id)
    {
    if (id < NUM_SEMAPHORES)
        {
        // Semaphore is already full, do nothing
        if (semaphores[id].full)
            {
            }
        // Semaphore has a task waiting, ready it to run
        else if (semaphores[id].waiting)
            {
            TCB *task = semaphores[id].waiting;

            task->ready = true;
            task->millis = millis();
            semaphores[id].waiting = NULL;
            }
        // Otherwise mark the semphore as full
        else
            {
            semaphores[id].full = true;
            }
        }
    }

void takeSem(uint8_t id)
    {
    if (id < NUM_SEMAPHORES)
        {
        // Semaphore is already full, take it and do not reschedule
        if (semaphores[id].full)
            {
            semaphores[id].full = false;
            }
        else
            // Semaphore is not full, we need to add ourselves to waiting
            // and reschedule
            {
            semaphores[id].waiting = runningTask;
            runningTask->ready = false;
            reschedule();
            }
        }
    }
<commit_msg>Added critical section global lock for use in semaphore routines<commit_after>/******************************************************************************
 *
 * Module      :  HaskinoRuntimeScheduler
 * Copyright   :  (c) University of Kansas
 * License     :  BSD3
 * Stability   :  experimental
 *
 * Haskino Runtime Scheduler module
 *****************************************************************************/

#include <Arduino.h>
#include "HaskinoRuntime.h"

// Scheduling routines
static void reschedule();
static void switchTo(TCB *newTask);
static bool minWait(TCB *task);
static void reschedule();

static TCB *firstTask = NULL;
static TCB *runningTask = NULL;
static int taskCount = 0;
static SEMAPHORE_C semaphores[NUM_SEMAPHORES];

// Temp variables used for C/Assembly transfer
volatile uint32_t taskStack;
volatile uint32_t taskFunction;

// Macros to save and restore context
#define SAVE_TASK_CONTEXT()\
asm volatile (\
"push r0                \n\t"\
"in r0, __SREG__        \n\t"\
"cli                    \n\t"\
"push r0                \n\t"\
"push r1                \n\t"\
"clr r1                 \n\t"\
"push r2                \n\t"\
"push r3                \n\t"\
"push r4                \n\t"\
"push r5                \n\t"\
"push r6                \n\t"\
"push r7                \n\t"\
"push r8                \n\t"\
"push r9                \n\t"\
"push r10               \n\t"\
"push r11               \n\t"\
"push r12               \n\t"\
"push r13               \n\t"\
"push r14               \n\t"\
"push r15               \n\t"\
"push r16               \n\t"\
"push r17               \n\t"\
"push r18               \n\t"\
"push r19               \n\t"\
"push r20               \n\t"\
"push r21               \n\t"\
"push r22               \n\t"\
"push r23               \n\t"\
"push r24               \n\t"\
"push r25               \n\t"\
"push r26               \n\t"\
"push r27               \n\t"\
"push r28               \n\t"\
"push r29               \n\t"\
"push r30               \n\t"\
"push r31               \n\t"\
"in r26, __SP_L__       \n\t"\
"in r27, __SP_H__       \n\t"\
"sts taskStack+1, r27   \n\t"\
"sts taskStack, r26     \n\t"\
"sei                    \n\t" : :);

#define LOAD_TASK_CONTEXT()\
asm volatile (\
"cli                    \n\t"\
"out __SP_L__, %A0      \n\t"\
"out __SP_H__, %B0      \n\t"\
"pop r31                \n\t"\
"pop r30                \n\t"\
"pop r29                \n\t"\
"pop r28                \n\t"\
"pop r27                \n\t"\
"pop r26                \n\t"\
"pop r25                \n\t"\
"pop r24                \n\t"\
"pop r23                \n\t"\
"pop r22                \n\t"\
"pop r21                \n\t"\
"pop r20                \n\t"\
"pop r19                \n\t"\
"pop r18                \n\t"\
"pop r17                \n\t"\
"pop r16                \n\t"\
"pop r15                \n\t"\
"pop r14                \n\t"\
"pop r13                \n\t"\
"pop r12                \n\t"\
"pop r11                \n\t"\
"pop r10                \n\t"\
"pop r9                 \n\t"\
"pop r8                 \n\t"\
"pop r7                 \n\t"\
"pop r6                 \n\t"\
"pop r5                 \n\t"\
"pop r4                 \n\t"\
"pop r3                 \n\t"\
"pop r2                 \n\t"\
"pop r1                 \n\t"\
"pop r0                 \n\t"\
"sei                    \n\t"\
"out __SREG__, r0       \n\t"\
"pop r0                 \n\t": : "r" (taskStack))

#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
    #define INIT_TASK_STACK_FUNC()\
    asm volatile(\
    "out __SP_L__, %A0  \n\t"\
    "out __SP_H__, %B0  \n\t"\
    "mov r0, %A1        \n\t"\
    "push r0            \n\t"\
    "mov r0, %B1        \n\t"\
    "push r0            \n\t"\
    "mov r0, %C1        \n\t"\
    "push r0            \n\t" : : "r" (taskStack), "r" (taskFunction))
#else
    #define INIT_TASK_STACK_FUNC()\
    asm volatile(\
    "out __SP_L__, %A0  \n\t"\
    "out __SP_H__, %B0  \n\t"\
    "mov r0, %A1        \n\t"\
    "push r0            \n\t"\
    "mov r0, %B1        \n\t"\
    "push r0            \n\t" : : "r" (taskStack), "r" (taskFunction))
#endif

static TCB *findTask(int id)
    {
    TCB *task = firstTask;

    while (task != NULL)
        {
        if (id == task->id)
            return task;
        task = task->next;
        }
    return NULL;
    }

void delayMilliseconds(uint32_t ms)
    {
#if 1
    runningTask->millis = millis() + ms;
    reschedule();
#else
    delay(ms);
#endif
    }

void createTask(uint8_t tid, void *tcb, int stackSize, void (*task)())
    {
    TCB *newTask = (TCB *) tcb;

    if (findTask(tid) == NULL)
        {
        newTask->next = firstTask;
        firstTask = newTask;
        newTask->id = tid;
        newTask->stackSize = stackSize;
        newTask->millis = 0;
        newTask->ready = false;
        newTask->hasRan = false;
        newTask->entry = task;
        newTask->stackPointer =
            (uint16_t) &newTask->stack[stackSize-sizeof(unsigned long)];
        taskCount++;
        }
    }

void deleteTask(uint8_t tid)
    {
    TCB *task;

    if ((task = findTask(tid)) != NULL)
        {
        task->ready = false;
        if (task == runningTask)
            reschedule();
        }
    }

void scheduleTask(uint8_t tid, uint32_t tt)
    {
    TCB *task;

    if ((task = findTask(tid)) != NULL)
        {
        task->millis = millis() + tt;
        task->ready = true;
        }
    }

void scheduleReset()
    {
    TCB *task = firstTask;

    // Set all tasks except for running one to false
    while (task != NULL)
        {
        if (task != runningTask)
            task->ready = false;
        task = task->next;
        }
    }

void taskComplete()
    {
    runningTask->ready = false;
    reschedule();
    }

static void switchTo(TCB *newTask)
    {
    SAVE_TASK_CONTEXT();
    runningTask->stackPointer = taskStack;

    runningTask = newTask;
    if(!runningTask->hasRan)
        {
        runningTask->hasRan = true;
        taskStack = (uint32_t) runningTask->stackPointer;
        taskFunction = (uint32_t) runningTask->entry;
        INIT_TASK_STACK_FUNC();
        }
    else
        {
        taskStack = (uint32_t) runningTask->stackPointer;
        LOAD_TASK_CONTEXT();
        }
    asm("ret");
    }

void startScheduler()
    {
    TCB *task;

    task = findTask(255);
    runningTask = task;
    switchTo(task);
    }

static bool minWait(TCB *task)
    {
    uint32_t now = millis();
    uint32_t minTime = 0x80000000UL;
    TCB *currTask = task;
    TCB *minTask = NULL;

    // Find the task that is ready to run and has the shortest delay
    do  {
        if (currTask->ready)
            {
            uint32_t timeDiff = currTask->millis - now;

            if (timeDiff >= 0x80000000UL)
                timeDiff = 0;
            if (timeDiff < minTime)
                {
                minTime = timeDiff;
                minTask = currTask;
                }
            }

        if (currTask->next == NULL)
            currTask = firstTask;
        else
            currTask = currTask->next;

        } while (currTask != task);

    // If one was found, then delay until its delay would time out
    // and switch to that task.
    if (minTask)
        {
        delay(minTime);
        if (minTask != runningTask)
            switchTo(minTask);
        return false;
        }
    else
        {
        return true;
        }
    }

static void reschedule()
    {
    TCB *next = runningTask->next;

    if (next == NULL)
        next = firstTask;

    // Loop while no tasks are ready.
    // Start the search with the task after the current one, so that
    // if all tasks used delayMillis(0), they would proceed in a
    // round robin fashion.

    while (minWait(next))
        {
        delay(1);
        }
    }

// Critical Region global lock routines

static inline uint8_t lock()
    {
    uint8_t statReg = SREG;
    cli();
    return statReg;
    }

static inline void unlock(uint8_t statReg)
    {
    SREG = statReg;
    }

// Semphore routines

void giveSem(uint8_t id)
    {
    if (id < NUM_SEMAPHORES)
        {
        uint8_t reg;

        reg = lock();
        // Semaphore is already full, do nothing
        if (semaphores[id].full)
            {
            }
        // Semaphore has a task waiting, ready it to run
        else if (semaphores[id].waiting)
            {
            TCB *task = semaphores[id].waiting;

            task->ready = true;
            task->millis = millis();
            semaphores[id].waiting = NULL;
            }
        // Otherwise mark the semphore as full
        else
            {
            semaphores[id].full = true;
            }
        unlock(reg);
        }
    }

void takeSem(uint8_t id)
    {
    if (id < NUM_SEMAPHORES)
        {
        uint8_t reg;

        reg = lock();
        // Semaphore is already full, take it and do not reschedule
        if (semaphores[id].full)
            {
            semaphores[id].full = false;
            unlock(reg);
            }
        else
            // Semaphore is not full, we need to add ourselves to waiting
            // and reschedule
            {
            semaphores[id].waiting = runningTask;
            runningTask->ready = false;
            unlock(reg);
            reschedule();
            }
        }
    }
<|endoftext|>


<commit_before>/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4:
#ident "$Id$"
/*======
This file is part of PerconaFT.

Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved.

    PerconaFT is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License, version 2,
    as published by the Free Software Foundation.

    PerconaFT is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with PerconaFT.  If not, see <http://www.gnu.org/licenses/>.

----------------------------------------

    PerconaFT is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License, version 3,
    as published by the Free Software Foundation.

    PerconaFT 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 Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with PerconaFT.  If not, see <http://www.gnu.org/licenses/>.
======= */

#ident "Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved."

#include "test.h"

static void
flush (CACHEFILE f __attribute__((__unused__)),
       int UU(fd),
       CACHEKEY k  __attribute__((__unused__)),
       void *v     __attribute__((__unused__)),
       void** UU(dd),
       void *e     __attribute__((__unused__)),
       PAIR_ATTR s      __attribute__((__unused__)),
       PAIR_ATTR* new_size      __attribute__((__unused__)),
       bool w      __attribute__((__unused__)),
       bool keep   __attribute__((__unused__)),
       bool c      __attribute__((__unused__)),
        bool UU(is_clone)
       ) {
  if (w) {
    assert(c);
    assert(keep);
  }
}

static void kibbutz_work(void *fe_v)
{
    CACHEFILE CAST_FROM_VOIDP(f1, fe_v);
    sleep(2);
    int r = toku_test_cachetable_unpin(f1, make_blocknum(1), 1, CACHETABLE_CLEAN, make_pair_attr(8));
    assert(r==0);
    remove_background_job_from_cf(f1);
}

static void
unlock_dummy (void* UU(v)) {
}

static void reset_unlockers(UNLOCKERS unlockers) {
    unlockers->locked = true;
}

static void
run_case_that_should_succeed(CACHEFILE f1, pair_lock_type first_lock, pair_lock_type second_lock) {
    void* v1;
    CACHETABLE_WRITE_CALLBACK wc = def_write_callback(NULL);
    wc.flush_callback = flush;
    struct unlockers unlockers = {true, unlock_dummy, NULL, NULL};
    int r = toku_cachetable_get_and_pin_nonblocking(f1, make_blocknum(1), 1, &v1, wc, def_fetch, def_pf_req_callback, def_pf_callback, first_lock, NULL, NULL);
    assert(r==0);
    cachefile_kibbutz_enq(f1, kibbutz_work, f1);
    reset_unlockers(&unlockers);
    r = toku_cachetable_get_and_pin_nonblocking(f1, make_blocknum(1), 1, &v1, wc, def_fetch, def_pf_req_callback, def_pf_callback, second_lock, NULL, &unlockers);
    assert(r==0); assert(unlockers.locked);
    r = toku_test_cachetable_unpin(f1, make_blocknum(1), 1, CACHETABLE_CLEAN, make_pair_attr(8)); assert(r==0);
}

static void
run_case_that_should_fail(CACHEFILE f1, pair_lock_type first_lock, pair_lock_type second_lock) {
    void* v1;
    CACHETABLE_WRITE_CALLBACK wc = def_write_callback(NULL);
    wc.flush_callback = flush;
    struct unlockers unlockers = {true, unlock_dummy, NULL, NULL};
    int r = toku_cachetable_get_and_pin_nonblocking(f1, make_blocknum(1), 1, &v1, wc, def_fetch, def_pf_req_callback, def_pf_callback, first_lock, NULL, NULL);
    assert(r==0);
    cachefile_kibbutz_enq(f1, kibbutz_work, f1);
    reset_unlockers(&unlockers);
    r = toku_cachetable_get_and_pin_nonblocking(f1, make_blocknum(1), 1, &v1, wc, def_fetch, def_pf_req_callback, def_pf_callback, second_lock, NULL, &unlockers);
    assert(r == TOKUDB_TRY_AGAIN); assert(!unlockers.locked);
}

static void
run_test (void) {
    const int test_limit = 12;
    int r;
    CACHETABLE ct;
    toku_cachetable_create(&ct, test_limit, ZERO_LSN, nullptr);
    const char *fname1 = TOKU_TEST_FILENAME;
    unlink(fname1);
    CACHEFILE f1;
    r = toku_cachetable_openf(&f1, ct, fname1, O_RDWR|O_CREAT, S_IRWXU|S_IRWXG|S_IRWXO); assert(r == 0);

    void* v1;
    CACHETABLE_WRITE_CALLBACK wc = def_write_callback(NULL);
    wc.flush_callback = flush;
    //
    // test that if we are getting a PAIR for the first time that TOKUDB_TRY_AGAIN is returned
    // because the PAIR was not in the cachetable.
    //
    r = toku_cachetable_get_and_pin_nonblocking(f1, make_blocknum(1), 1, &v1, wc, def_fetch, def_pf_req_callback, def_pf_callback, PL_WRITE_EXPENSIVE, NULL, NULL);
    assert(r==TOKUDB_TRY_AGAIN);

    run_case_that_should_succeed(f1, PL_READ, PL_WRITE_CHEAP);
    run_case_that_should_succeed(f1, PL_READ, PL_WRITE_EXPENSIVE);

    run_case_that_should_succeed(f1, PL_WRITE_CHEAP, PL_READ);
    run_case_that_should_succeed(f1, PL_WRITE_CHEAP, PL_WRITE_CHEAP);
    run_case_that_should_succeed(f1, PL_WRITE_CHEAP, PL_WRITE_EXPENSIVE);

    run_case_that_should_fail(f1, PL_WRITE_EXPENSIVE, PL_READ);
    run_case_that_should_fail(f1, PL_WRITE_EXPENSIVE, PL_WRITE_CHEAP);
    run_case_that_should_fail(f1, PL_WRITE_EXPENSIVE, PL_WRITE_EXPENSIVE);

    toku_cachetable_verify(ct);
    toku_cachefile_close(&f1, false, ZERO_LSN);
    toku_cachetable_close(&ct);
}

int
test_main(int argc, const char *argv[]) {
  default_parse_args(argc, argv);
  run_test();
  return 0;
}
<commit_msg>The cachetable-simple-pin-noblocking-cheap test occasionally fails due to a TOKUDB_TRY_AGAIN error being kicked out of the cachetable to the test.  The test does not expect this error so it crashes.  The TOKUDB_TRY_AGAIN error was caused by a locking conflict between the test and the cachetable evictor which periodically runs on a background thread.  Since the evictor is not an important part of this test, its execution was removed by setting the cachetable size larger than the test's cachetable footprint.<commit_after>/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4:
#ident "$Id$"
/*======
This file is part of PerconaFT.

Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved.

    PerconaFT is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License, version 2,
    as published by the Free Software Foundation.

    PerconaFT is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with PerconaFT.  If not, see <http://www.gnu.org/licenses/>.

----------------------------------------

    PerconaFT is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License, version 3,
    as published by the Free Software Foundation.

    PerconaFT 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 Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with PerconaFT.  If not, see <http://www.gnu.org/licenses/>.
======= */

#ident "Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved."

#include "test.h"

static void
flush (CACHEFILE f __attribute__((__unused__)),
       int UU(fd),
       CACHEKEY k  __attribute__((__unused__)),
       void *v     __attribute__((__unused__)),
       void** UU(dd),
       void *e     __attribute__((__unused__)),
       PAIR_ATTR s      __attribute__((__unused__)),
       PAIR_ATTR* new_size      __attribute__((__unused__)),
       bool w      __attribute__((__unused__)),
       bool keep   __attribute__((__unused__)),
       bool c      __attribute__((__unused__)),
        bool UU(is_clone)
       ) {
  if (w) {
    assert(c);
    assert(keep);
  }
}

static void kibbutz_work(void *fe_v)
{
    CACHEFILE CAST_FROM_VOIDP(f1, fe_v);
    sleep(2);
    int r = toku_test_cachetable_unpin(f1, make_blocknum(1), 1, CACHETABLE_CLEAN, make_pair_attr(8));
    assert(r==0);
    remove_background_job_from_cf(f1);
}

static void
unlock_dummy (void* UU(v)) {
}

static void reset_unlockers(UNLOCKERS unlockers) {
    unlockers->locked = true;
}

static void
run_case_that_should_succeed(CACHEFILE f1, pair_lock_type first_lock, pair_lock_type second_lock) {
    void* v1;
    CACHETABLE_WRITE_CALLBACK wc = def_write_callback(NULL);
    wc.flush_callback = flush;
    struct unlockers unlockers = {true, unlock_dummy, NULL, NULL};
    int r = toku_cachetable_get_and_pin_nonblocking(f1, make_blocknum(1), 1, &v1, wc, def_fetch, def_pf_req_callback, def_pf_callback, first_lock, NULL, NULL);
    assert(r==0);
    cachefile_kibbutz_enq(f1, kibbutz_work, f1);
    reset_unlockers(&unlockers);
    r = toku_cachetable_get_and_pin_nonblocking(f1, make_blocknum(1), 1, &v1, wc, def_fetch, def_pf_req_callback, def_pf_callback, second_lock, NULL, &unlockers);
    assert(r==0); assert(unlockers.locked);
    r = toku_test_cachetable_unpin(f1, make_blocknum(1), 1, CACHETABLE_CLEAN, make_pair_attr(8)); assert(r==0);
}

static void
run_case_that_should_fail(CACHEFILE f1, pair_lock_type first_lock, pair_lock_type second_lock) {
    void* v1;
    CACHETABLE_WRITE_CALLBACK wc = def_write_callback(NULL);
    wc.flush_callback = flush;
    struct unlockers unlockers = {true, unlock_dummy, NULL, NULL};
    int r = toku_cachetable_get_and_pin_nonblocking(f1, make_blocknum(1), 1, &v1, wc, def_fetch, def_pf_req_callback, def_pf_callback, first_lock, NULL, NULL);
    assert(r==0);
    cachefile_kibbutz_enq(f1, kibbutz_work, f1);
    reset_unlockers(&unlockers);
    r = toku_cachetable_get_and_pin_nonblocking(f1, make_blocknum(1), 1, &v1, wc, def_fetch, def_pf_req_callback, def_pf_callback, second_lock, NULL, &unlockers);
    assert(r == TOKUDB_TRY_AGAIN); assert(!unlockers.locked);
}

static void
run_test (void) {
    // sometimes the cachetable evictor runs during the test.  this sometimes causes cachetable pair locking contention,
    // which results with a TOKUDB_TRY_AGAIN error occurring.  unfortunately, the test does not expect this and fails.
    // set cachetable size limit to a value big enough so that the cachetable evictor is not triggered during the test.
    const int test_limit = 100;

    int r;
    CACHETABLE ct;
    toku_cachetable_create(&ct, test_limit, ZERO_LSN, nullptr);
    const char *fname1 = TOKU_TEST_FILENAME;
    unlink(fname1);
    CACHEFILE f1;
    r = toku_cachetable_openf(&f1, ct, fname1, O_RDWR|O_CREAT, S_IRWXU|S_IRWXG|S_IRWXO); assert(r == 0);

    void* v1;
    CACHETABLE_WRITE_CALLBACK wc = def_write_callback(NULL);
    wc.flush_callback = flush;
    //
    // test that if we are getting a PAIR for the first time that TOKUDB_TRY_AGAIN is returned
    // because the PAIR was not in the cachetable.
    //
    r = toku_cachetable_get_and_pin_nonblocking(f1, make_blocknum(1), 1, &v1, wc, def_fetch, def_pf_req_callback, def_pf_callback, PL_WRITE_EXPENSIVE, NULL, NULL);
    assert(r==TOKUDB_TRY_AGAIN);

    run_case_that_should_succeed(f1, PL_READ, PL_WRITE_CHEAP);
    run_case_that_should_succeed(f1, PL_READ, PL_WRITE_EXPENSIVE);

    run_case_that_should_succeed(f1, PL_WRITE_CHEAP, PL_READ);
    run_case_that_should_succeed(f1, PL_WRITE_CHEAP, PL_WRITE_CHEAP);
    run_case_that_should_succeed(f1, PL_WRITE_CHEAP, PL_WRITE_EXPENSIVE);

    run_case_that_should_fail(f1, PL_WRITE_EXPENSIVE, PL_READ);
    run_case_that_should_fail(f1, PL_WRITE_EXPENSIVE, PL_WRITE_CHEAP);
    run_case_that_should_fail(f1, PL_WRITE_EXPENSIVE, PL_WRITE_EXPENSIVE);

    toku_cachetable_verify(ct);
    toku_cachefile_close(&f1, false, ZERO_LSN);
    toku_cachetable_close(&ct);
}

int
test_main(int argc, const char *argv[]) {
  default_parse_args(argc, argv);
  run_test();
  return 0;
}
<|endoftext|>


<commit_before>
#pragma once

#include <gloperate/base/make_unique.hpp>
#include <gloperate/pipeline/AbstractPipeline.h>

#include "DummyStage.hpp"

using namespace gloperate;

class TestPipeline : public AbstractPipeline
{
public:
    TestPipeline()
    {
        auto stage0 = make_unique<DummyStage>("", std::vector<std::string>{}, std::vector<std::string>{"output0", "output1"});
        auto stage1 = make_unique<DummyStage>("", std::vector<std::string>{"input0"}, std::vector<std::string>{"output0"});
        auto stage2 = make_unique<DummyStage>("", std::vector<std::string>{"input0"}, std::vector<std::string>{"output0"});
        auto stage3 = make_unique<DummyStage>("", std::vector<std::string>{"input0", "input1"}, std::vector<std::string>{"output0"});
        auto stage4 = make_unique<DummyStage>("", std::vector<std::string>{"input0"}, std::vector<std::string>{"output0"});
        auto stage5 = make_unique<DummyStage>("", std::vector<std::string>{"input0", "input1"}, std::vector<std::string>{"output0"});
        auto stage6 = make_unique<DummyStage>("", std::vector<std::string>{"input0", "input1"}, std::vector<std::string>{"output0"});
        auto stage7 = make_unique<DummyStage>("", std::vector<std::string>{"input0", "input1"}, std::vector<std::string>{"output0"});
        auto stage8 = make_unique<DummyStage>("", std::vector<std::string>{"input0", "input1", "input2"}, std::vector<std::string>{"output0"});
        auto stage9 = make_unique<DummyStage>("", std::vector<std::string>{"input0", "input1", "input2"}, std::vector<std::string>{"output0"});
        auto stage10 = make_unique<DummyStage>("", std::vector<std::string>{"input0", "input1", "input2"}, std::vector<std::string>{"output0"});
        auto stage11 = make_unique<DummyStage>("", std::vector<std::string>{"input0"}, std::vector<std::string>{"output0"});
        auto stage12 = make_unique<DummyStage>("", std::vector<std::string>{"input0", "input1", "input2"}, std::vector<std::string>{"output0"});
        auto stage13 = make_unique<DummyStage>("", std::vector<std::string>{"input0", "input1", "input2", "input3", "input4"}, std::vector<std::string>{"output0"});
        auto stage14 = make_unique<DummyStage>("", std::vector<std::string>{"input0"}, std::vector<std::string>{"output0", "output1", "output2", "output3", "output4"});
        auto stage15 = make_unique<DummyStage>("", std::vector<std::string>{"input0", "input1", "input2", "input3", "input4", "input5"}, std::vector<std::string>{"output0"});
        auto stage16 = make_unique<DummyStage>("", std::vector<std::string>{"input0"}, std::vector<std::string>{});

        stage1->inputs.at("input0") = stage0->outputs.at("output0");

        stage2->inputs.at("input0") = stage1->outputs.at("output0");

        stage3->inputs.at("input0") = stage0->outputs.at("output0");
        stage3->inputs.at("input1") = stage2->outputs.at("output0");

        stage4->inputs.at("input0") = stage3->outputs.at("output0");

        stage5->inputs.at("input0") = stage3->outputs.at("output0");
        stage5->inputs.at("input1") = stage4->outputs.at("output0");

        stage6->inputs.at("input0") = stage3->outputs.at("output0");
        stage6->inputs.at("input1") = stage4->outputs.at("output0");

        stage7->inputs.at("input0") = stage3->outputs.at("output0");
        stage7->inputs.at("input0") = stage4->outputs.at("output0");

        stage8->inputs.at("input0") = stage3->outputs.at("output0");
        stage8->inputs.at("input1") = stage4->outputs.at("output0");
        stage8->inputs.at("input2") = stage5->outputs.at("output0");

        stage9->inputs.at("input0") = stage3->outputs.at("output0");
        stage9->inputs.at("input1") = stage4->outputs.at("output0");
        stage9->inputs.at("input2") = stage6->outputs.at("output0");

        stage10->inputs.at("input0") = stage3->outputs.at("output0");
        stage10->inputs.at("input1") = stage4->outputs.at("output0");
        stage10->inputs.at("input2") = stage7->outputs.at("output0");

        stage11->inputs.at("input0") = stage10->outputs.at("output0");

        stage12->inputs.at("input0") = stage3->outputs.at("output0");
        stage12->inputs.at("input1") = stage4->outputs.at("output0");
        stage12->inputs.at("input2") = stage8->outputs.at("output0");

        stage13->inputs.at("input0") = stage3->outputs.at("output0");
        stage13->inputs.at("input1") = stage4->outputs.at("output0");
        stage13->inputs.at("input2") = stage12->outputs.at("output0");
        stage13->inputs.at("input3") = stage9->outputs.at("output0");
        stage13->inputs.at("input4") = stage11->outputs.at("output0");

        stage14->inputs.at("input0") = stage13->outputs.at("output0");

        stage15->inputs.at("input0") = stage14->outputs.at("output0");
        stage15->inputs.at("input1") = stage14->outputs.at("output1");
        stage15->inputs.at("input2") = stage14->outputs.at("output2");
        stage15->inputs.at("input3") = stage14->outputs.at("output3");
        stage15->inputs.at("input4") = stage14->outputs.at("output4");
        stage15->inputs.at("input5") = stage0->outputs.at("output1");

        stage16->inputs.at("input0") = stage15->outputs.at("output0");

        addStages(
            std::move(stage0),
            std::move(stage1),
            std::move(stage2),
            std::move(stage3),
            std::move(stage4),
            std::move(stage5),
            std::move(stage6),
            std::move(stage7),
            std::move(stage8),
            std::move(stage9),
            std::move(stage10),
            std::move(stage11),
            std::move(stage12),
            std::move(stage13),
            std::move(stage14),
            std::move(stage15),
            std::move(stage16));
    }

};
<commit_msg>fix ambiguous make_unique call<commit_after>
#pragma once

#include <gloperate/base/make_unique.hpp>
#include <gloperate/pipeline/AbstractPipeline.h>

#include "DummyStage.hpp"

using namespace gloperate;
using gloperate::make_unique;

class TestPipeline : public AbstractPipeline
{
public:
    TestPipeline()
    {
        auto stage0 = make_unique<DummyStage>("", std::vector<std::string>{}, std::vector<std::string>{"output0", "output1"});
        auto stage1 = make_unique<DummyStage>("", std::vector<std::string>{"input0"}, std::vector<std::string>{"output0"});
        auto stage2 = make_unique<DummyStage>("", std::vector<std::string>{"input0"}, std::vector<std::string>{"output0"});
        auto stage3 = make_unique<DummyStage>("", std::vector<std::string>{"input0", "input1"}, std::vector<std::string>{"output0"});
        auto stage4 = make_unique<DummyStage>("", std::vector<std::string>{"input0"}, std::vector<std::string>{"output0"});
        auto stage5 = make_unique<DummyStage>("", std::vector<std::string>{"input0", "input1"}, std::vector<std::string>{"output0"});
        auto stage6 = make_unique<DummyStage>("", std::vector<std::string>{"input0", "input1"}, std::vector<std::string>{"output0"});
        auto stage7 = make_unique<DummyStage>("", std::vector<std::string>{"input0", "input1"}, std::vector<std::string>{"output0"});
        auto stage8 = make_unique<DummyStage>("", std::vector<std::string>{"input0", "input1", "input2"}, std::vector<std::string>{"output0"});
        auto stage9 = make_unique<DummyStage>("", std::vector<std::string>{"input0", "input1", "input2"}, std::vector<std::string>{"output0"});
        auto stage10 = make_unique<DummyStage>("", std::vector<std::string>{"input0", "input1", "input2"}, std::vector<std::string>{"output0"});
        auto stage11 = make_unique<DummyStage>("", std::vector<std::string>{"input0"}, std::vector<std::string>{"output0"});
        auto stage12 = make_unique<DummyStage>("", std::vector<std::string>{"input0", "input1", "input2"}, std::vector<std::string>{"output0"});
        auto stage13 = make_unique<DummyStage>("", std::vector<std::string>{"input0", "input1", "input2", "input3", "input4"}, std::vector<std::string>{"output0"});
        auto stage14 = make_unique<DummyStage>("", std::vector<std::string>{"input0"}, std::vector<std::string>{"output0", "output1", "output2", "output3", "output4"});
        auto stage15 = make_unique<DummyStage>("", std::vector<std::string>{"input0", "input1", "input2", "input3", "input4", "input5"}, std::vector<std::string>{"output0"});
        auto stage16 = make_unique<DummyStage>("", std::vector<std::string>{"input0"}, std::vector<std::string>{});

        stage1->inputs.at("input0") = stage0->outputs.at("output0");

        stage2->inputs.at("input0") = stage1->outputs.at("output0");

        stage3->inputs.at("input0") = stage0->outputs.at("output0");
        stage3->inputs.at("input1") = stage2->outputs.at("output0");

        stage4->inputs.at("input0") = stage3->outputs.at("output0");

        stage5->inputs.at("input0") = stage3->outputs.at("output0");
        stage5->inputs.at("input1") = stage4->outputs.at("output0");

        stage6->inputs.at("input0") = stage3->outputs.at("output0");
        stage6->inputs.at("input1") = stage4->outputs.at("output0");

        stage7->inputs.at("input0") = stage3->outputs.at("output0");
        stage7->inputs.at("input0") = stage4->outputs.at("output0");

        stage8->inputs.at("input0") = stage3->outputs.at("output0");
        stage8->inputs.at("input1") = stage4->outputs.at("output0");
        stage8->inputs.at("input2") = stage5->outputs.at("output0");

        stage9->inputs.at("input0") = stage3->outputs.at("output0");
        stage9->inputs.at("input1") = stage4->outputs.at("output0");
        stage9->inputs.at("input2") = stage6->outputs.at("output0");

        stage10->inputs.at("input0") = stage3->outputs.at("output0");
        stage10->inputs.at("input1") = stage4->outputs.at("output0");
        stage10->inputs.at("input2") = stage7->outputs.at("output0");

        stage11->inputs.at("input0") = stage10->outputs.at("output0");

        stage12->inputs.at("input0") = stage3->outputs.at("output0");
        stage12->inputs.at("input1") = stage4->outputs.at("output0");
        stage12->inputs.at("input2") = stage8->outputs.at("output0");

        stage13->inputs.at("input0") = stage3->outputs.at("output0");
        stage13->inputs.at("input1") = stage4->outputs.at("output0");
        stage13->inputs.at("input2") = stage12->outputs.at("output0");
        stage13->inputs.at("input3") = stage9->outputs.at("output0");
        stage13->inputs.at("input4") = stage11->outputs.at("output0");

        stage14->inputs.at("input0") = stage13->outputs.at("output0");

        stage15->inputs.at("input0") = stage14->outputs.at("output0");
        stage15->inputs.at("input1") = stage14->outputs.at("output1");
        stage15->inputs.at("input2") = stage14->outputs.at("output2");
        stage15->inputs.at("input3") = stage14->outputs.at("output3");
        stage15->inputs.at("input4") = stage14->outputs.at("output4");
        stage15->inputs.at("input5") = stage0->outputs.at("output1");

        stage16->inputs.at("input0") = stage15->outputs.at("output0");

        addStages(
            std::move(stage0),
            std::move(stage1),
            std::move(stage2),
            std::move(stage3),
            std::move(stage4),
            std::move(stage5),
            std::move(stage6),
            std::move(stage7),
            std::move(stage8),
            std::move(stage9),
            std::move(stage10),
            std::move(stage11),
            std::move(stage12),
            std::move(stage13),
            std::move(stage14),
            std::move(stage15),
            std::move(stage16));
    }

};
<|endoftext|>


<commit_before>//============================================================================
// Name        : CubemapRenderer.h
// Author      : Duarte Peixinho
// Version     :
// Copyright   : ;)
// Description : Dynamic Cube Map aka Environment Map
//============================================================================

#include "CubemapRenderer.h"
#include <GL/glew.h>

namespace p3d {

    CubemapRenderer::CubemapRenderer(const uint32& Width, const uint32& Height) : IRenderer(Width,Height)
    {

        echo("SUCCESS: Forward Renderer Created");

        ActivateCulling(CullingMode::FrustumCulling);

        // Create Texture (CubeMap), Frame Buffer and Set the Texture as Attachment
        environmentMap=AssetManager::CreateTexture(TextureType::CubemapNegative_X,TextureDataType::RGB,Width,Height,false);
        environmentMap->CreateTexture(TextureType::CubemapNegative_Y,TextureDataType::RGB,Width,Height,false);
        environmentMap->CreateTexture(TextureType::CubemapNegative_Z,TextureDataType::RGB,Width,Height,false);
        environmentMap->CreateTexture(TextureType::CubemapPositive_X,TextureDataType::RGB,Width,Height,false);
        environmentMap->CreateTexture(TextureType::CubemapPositive_Y,TextureDataType::RGB,Width,Height,false);
        environmentMap->CreateTexture(TextureType::CubemapPositive_Z,TextureDataType::RGB,Width,Height,false);
        environmentMap->SetRepeat(TextureRepeat::ClampToEdge,TextureRepeat::ClampToEdge,TextureRepeat::ClampToEdge);

        // Initialize Frame Buffer
        fbo = new FrameBuffer();
        fbo->Init(FrameBufferAttachmentFormat::Color_Attachment0,TextureType::CubemapPositive_X,environmentMap,true);

    }

    CubemapRenderer::~CubemapRenderer()
    {
        if (IsCulling)
        {
            delete culling;
        }

        AssetManager::DeleteTexture(environmentMap);
        delete fbo;
    }

    std::vector<RenderingMesh*> CubemapRenderer::GroupAndSortAssets(SceneGraph* Scene, GameObject* Camera)
    {

        // Sort and Group Objects From Scene
        std::vector<RenderingMesh*> _OpaqueMeshes;
        std::map<f32,RenderingMesh*> _TranslucidMeshes;

        std::vector<RenderingMesh*> rmeshes = RenderingComponent::GetRenderingMeshes(Scene);

        for (std::vector<RenderingMesh*>::iterator k=rmeshes.begin();k!=rmeshes.end();k++)
        {
            if ((*k)->Material->IsTransparent())
            {
                f32 index = Camera->GetWorldPosition().distanceSQR((*k)->renderingComponent->GetOwner()->GetWorldPosition());
                while(_TranslucidMeshes.find(index)!=_TranslucidMeshes.end()) index+=1.f;
                _TranslucidMeshes[index] = (*k);
            }
            else _OpaqueMeshes.push_back((*k));
        }

        for (std::map<f32,RenderingMesh*>::iterator i=_TranslucidMeshes.begin();i!=_TranslucidMeshes.end();i++)
        {
            _OpaqueMeshes.push_back((*i).second);
        }

        return _OpaqueMeshes;

    }

    void CubemapRenderer::RenderCubeMap(SceneGraph* Scene, GameObject* AllSeeingEye, const f32 &Near, const f32 &Far)
    {

        InitRender();

        this->AllSeeingEye = AllSeeingEye;
        ProjectionMatrix = Matrix::PerspectiveMatrix(90.f, 1.0, Near, Far);

        // Universal Cache
        NearFarPlane = Vec2(Near, Far);
        CameraPosition = AllSeeingEye->GetWorldPosition();

        // Flags
        ViewMatrixInverseIsDirty = true;
        ProjectionMatrixInverseIsDirty = true;
        ViewProjectionMatrixIsDirty = true;

        // Group and Sort Meshes
        std::vector<RenderingMesh*> rmesh = GroupAndSortAssets(Scene,AllSeeingEye);

        // Get Lights List
        std::vector<IComponent*> lcomps = ILightComponent::GetLightsOnScene(Scene);

        if (rmesh.size()>0)
        {

            // Prepare and Pack Lights to Send to Shaders
            Lights.clear();

            // ShadowMaps
            DirectionalShadowMapsTextures.clear();
            DirectionalShadowMatrix.clear();
            NumberOfDirectionalShadows = 0;

            PointShadowMapsTextures.clear();
            PointShadowMatrix.clear();
            NumberOfPointShadows = 0;

            SpotShadowMapsTextures.clear();
            SpotShadowMatrix.clear();
            NumberOfSpotShadows = 0;

            if (lcomps.size()>0)
            {
                for (std::vector<IComponent*>::iterator i = lcomps.begin();i!=lcomps.end();i++)
                {
                    if (DirectionalLight* d = dynamic_cast<DirectionalLight*>((*i))) {

                        // Directional Lights
                        Vec4 color = d->GetLightColor();
                        Vec3 position;
                        Vec3 LDirection = d->GetOwner()->GetWorldPosition().normalize();
                        Vec4 direction = ViewMatrix * Vec4(LDirection.x,LDirection.y,LDirection.z,0.f);
                        f32 attenuation = 1.f;
                        Vec2 cones;
                        int32 type = 1;

                        Matrix directionalLight = Matrix();
                        directionalLight.m[0] = color.x;         directionalLight.m[1] = color.y;             directionalLight.m[2] = color.z;             directionalLight.m[3] = color.w;
                        directionalLight.m[4] = position.x;      directionalLight.m[5] = position.y;          directionalLight.m[6] = position.z;
                        directionalLight.m[7] = direction.x;     directionalLight.m[8] = direction.y;         directionalLight.m[9] = direction.z;
                        directionalLight.m[10] = attenuation;   //directionalLight.m[11] = attenuation.y;       directionalLight.m[12] = attenuation.z;
                        directionalLight.m[13] = cones.x;         directionalLight.m[14] = cones.y;
                        directionalLight.m[15] = type;

                        Lights.push_back(directionalLight);

                    } else if (PointLight* p = dynamic_cast<PointLight*>((*i))) {

                        // Point Lights
                        Vec4 color = p->GetLightColor();
                        Vec3 position = ViewMatrix * (p->GetOwner()->GetWorldPosition());
                        Vec3 direction;
                        f32 attenuation = p->GetLightRadius();
                        Vec2 cones;
                        int32 type = 2;

                        Matrix pointLight = Matrix();
                        pointLight.m[0] = color.x;       pointLight.m[1] = color.y;           pointLight.m[2] = color.z;           pointLight.m[3] = color.w;
                        pointLight.m[4] = position.x;    pointLight.m[5] = position.y;        pointLight.m[6] = position.z;
                        pointLight.m[7] = direction.x;   pointLight.m[8] = direction.y;       pointLight.m[9] = direction.z;
                        pointLight.m[10] = attenuation; //pointLight.m[11] = attenuation.y;     pointLight.m[12] = attenuation.z;
                        pointLight.m[13] = cones.x;       pointLight.m[14] = cones.y;
                        pointLight.m[15] = type;

                        Lights.push_back(pointLight);

                    } else if (SpotLight* s = dynamic_cast<SpotLight*>((*i))) {

                        // Spot Lights
                        Vec4 color = s->GetLightColor();
                        Vec3 position = ViewMatrix * (s->GetOwner()->GetWorldPosition());
                        Vec3 LDirection = s->GetLightDirection().normalize();
                        Vec4 direction = ViewMatrix * Vec4(LDirection.x,LDirection.y,LDirection.z,0.f);
                        f32 attenuation = s->GetLightRadius();
                        Vec2 cones = Vec2(s->GetLightCosInnerCone(),s->GetLightCosOutterCone());
                        int32 type = 3;

                        Matrix spotLight = Matrix();
                        spotLight.m[0] = color.x;        spotLight.m[1] = color.y;            spotLight.m[2] = color.z;            spotLight.m[3] = color.w;
                        spotLight.m[4] = position.x;     spotLight.m[5] = position.y;         spotLight.m[6] = position.z;
                        spotLight.m[7] = direction.x;    spotLight.m[8] = direction.y;        spotLight.m[9] = direction.z;
                        spotLight.m[10] = attenuation;  //spotLight.m[11] = attenuation.y;      spotLight.m[12] = attenuation.z;
                        spotLight.m[13] = cones.x;        spotLight.m[14] = cones.y;
                        spotLight.m[15] = type;

                        Lights.push_back(spotLight);
                    }
                }
            }

            // Save Time
            Timer = Scene->GetTime();

            // Update Lights Position and Direction to ViewSpace
            NumberOfLights = Lights.size();

            // Bind FBO
            fbo->Bind();

            for (uint32 i=0;i<6;i++)
            {
                // Clean View Matrix
                ViewMatrix.identity();

                // Create Light View Matrix For Rendering Each Face of the Cubemap
                if (i==0)
                    ViewMatrix.LookAt(Vec3::ZERO, Vec3(1.0, 0.0, 0.0), Vec3(0.0,-1.0,0.0)); // +X
                if (i==1)
                    ViewMatrix.LookAt(Vec3::ZERO, Vec3(-1.0, 0.0, 0.0), Vec3(0.0,-1.0,0.0)); // -X
                if (i==2)
                    ViewMatrix.LookAt(Vec3::ZERO, Vec3(0.0, -1.0, 0.0), Vec3(0.0,0.0,1.0)); // +Y
                if (i==3)
                    ViewMatrix.LookAt(Vec3::ZERO, Vec3(0.0, 1.0, 0.0), Vec3(0.0,0.0,-1.0)); // -Y
                if (i==4)
                    ViewMatrix.LookAt(Vec3::ZERO, Vec3(0.0, 0.0, 1.0), Vec3(0.0,-1.0,0.0)); // +Z
                if (i==5)
                    ViewMatrix.LookAt(Vec3::ZERO, Vec3(0.0, 0.0, -1.0), Vec3(0.0,-1.0,0.0)); // -Z

                // Translate Light View Matrix
                ViewMatrix*=AllSeeingEye->GetWorldTransformation().Inverse();

                // Frame Buffer Attachment
                fbo->AddAttach(FrameBufferAttachmentFormat::Color_Attachment0,TextureType::CubemapPositive_X+i,environmentMap);

                // Set Viewport
                SetViewPort(0,0, Width, Height);

                // Clear Screen
                ClearScreen(Buffer_Bit::Color | Buffer_Bit::Depth);
                SetBackground(Vec4::ZERO);
                EnableDepthTest();

                // Update Culling
                UpdateCulling(ProjectionMatrix*ViewMatrix);

                // Render Scene with Objects Material
                for (std::vector<RenderingMesh*>::iterator k=rmesh.begin();k!=rmesh.end();k++)
                {

                    if ((*k)->renderingComponent->GetOwner()!=NULL)
                    {
                        // Culling Test
                        bool cullingTest = false;
                        switch((*k)->CullingGeometry)
                        {
                            case CullingGeometry::Box:
                                cullingTest = CullingBoxTest(*k);
                                break;
                            case CullingGeometry::Sphere:
                            default:
                                cullingTest = CullingSphereTest(*k);
                                break;
                        }
                        if (cullingTest && (*k)->renderingComponent->IsActive())
                            RenderObject((*k),(*k)->Material);
                    }
                }
            }

            fbo->UnBind();

            EndRender();
        }
    }

    Texture* CubemapRenderer::GetTexture()
    {
        return environmentMap;
    }

};<commit_msg>Fixed minore issue when creating view matrix, it was flipped on Y (on purpose for testing :P)<commit_after>//============================================================================
// Name        : CubemapRenderer.h
// Author      : Duarte Peixinho
// Version     :
// Copyright   : ;)
// Description : Dynamic Cube Map aka Environment Map
//============================================================================

#include "CubemapRenderer.h"
#include <GL/glew.h>

namespace p3d {

    CubemapRenderer::CubemapRenderer(const uint32& Width, const uint32& Height) : IRenderer(Width,Height)
    {

        echo("SUCCESS: Forward Renderer Created");

        ActivateCulling(CullingMode::FrustumCulling);

        // Create Texture (CubeMap), Frame Buffer and Set the Texture as Attachment
        environmentMap=AssetManager::CreateTexture(TextureType::CubemapNegative_X,TextureDataType::RGB,Width,Height,false);
        environmentMap->CreateTexture(TextureType::CubemapNegative_Y,TextureDataType::RGB,Width,Height,false);
        environmentMap->CreateTexture(TextureType::CubemapNegative_Z,TextureDataType::RGB,Width,Height,false);
        environmentMap->CreateTexture(TextureType::CubemapPositive_X,TextureDataType::RGB,Width,Height,false);
        environmentMap->CreateTexture(TextureType::CubemapPositive_Y,TextureDataType::RGB,Width,Height,false);
        environmentMap->CreateTexture(TextureType::CubemapPositive_Z,TextureDataType::RGB,Width,Height,false);
        environmentMap->SetRepeat(TextureRepeat::ClampToEdge,TextureRepeat::ClampToEdge,TextureRepeat::ClampToEdge);

        // Initialize Frame Buffer
        fbo = new FrameBuffer();
        fbo->Init(FrameBufferAttachmentFormat::Color_Attachment0,TextureType::CubemapPositive_X,environmentMap,true);

    }

    CubemapRenderer::~CubemapRenderer()
    {
        if (IsCulling)
        {
            delete culling;
        }

        AssetManager::DeleteTexture(environmentMap);
        delete fbo;
    }

    std::vector<RenderingMesh*> CubemapRenderer::GroupAndSortAssets(SceneGraph* Scene, GameObject* Camera)
    {

        // Sort and Group Objects From Scene
        std::vector<RenderingMesh*> _OpaqueMeshes;
        std::map<f32,RenderingMesh*> _TranslucidMeshes;

        std::vector<RenderingMesh*> rmeshes = RenderingComponent::GetRenderingMeshes(Scene);

        for (std::vector<RenderingMesh*>::iterator k=rmeshes.begin();k!=rmeshes.end();k++)
        {
            if ((*k)->Material->IsTransparent())
            {
                f32 index = Camera->GetWorldPosition().distanceSQR((*k)->renderingComponent->GetOwner()->GetWorldPosition());
                while(_TranslucidMeshes.find(index)!=_TranslucidMeshes.end()) index+=1.f;
                _TranslucidMeshes[index] = (*k);
            }
            else _OpaqueMeshes.push_back((*k));
        }

        for (std::map<f32,RenderingMesh*>::iterator i=_TranslucidMeshes.begin();i!=_TranslucidMeshes.end();i++)
        {
            _OpaqueMeshes.push_back((*i).second);
        }

        return _OpaqueMeshes;

    }

    void CubemapRenderer::RenderCubeMap(SceneGraph* Scene, GameObject* AllSeeingEye, const f32 &Near, const f32 &Far)
    {

        InitRender();

        this->AllSeeingEye = AllSeeingEye;
        ProjectionMatrix = Matrix::PerspectiveMatrix(90.f, 1.0, Near, Far);

        // Universal Cache
        NearFarPlane = Vec2(Near, Far);
        CameraPosition = AllSeeingEye->GetWorldPosition();

        // Flags
        ViewMatrixInverseIsDirty = true;
        ProjectionMatrixInverseIsDirty = true;
        ViewProjectionMatrixIsDirty = true;

        // Group and Sort Meshes
        std::vector<RenderingMesh*> rmesh = GroupAndSortAssets(Scene,AllSeeingEye);

        // Get Lights List
        std::vector<IComponent*> lcomps = ILightComponent::GetLightsOnScene(Scene);

        if (rmesh.size()>0)
        {

            // Prepare and Pack Lights to Send to Shaders
            Lights.clear();

            // ShadowMaps
            DirectionalShadowMapsTextures.clear();
            DirectionalShadowMatrix.clear();
            NumberOfDirectionalShadows = 0;

            PointShadowMapsTextures.clear();
            PointShadowMatrix.clear();
            NumberOfPointShadows = 0;

            SpotShadowMapsTextures.clear();
            SpotShadowMatrix.clear();
            NumberOfSpotShadows = 0;

            if (lcomps.size()>0)
            {
                for (std::vector<IComponent*>::iterator i = lcomps.begin();i!=lcomps.end();i++)
                {
                    if (DirectionalLight* d = dynamic_cast<DirectionalLight*>((*i))) {

                        // Directional Lights
                        Vec4 color = d->GetLightColor();
                        Vec3 position;
                        Vec3 LDirection = d->GetOwner()->GetWorldPosition().normalize();
                        Vec4 direction = ViewMatrix * Vec4(LDirection.x,LDirection.y,LDirection.z,0.f);
                        f32 attenuation = 1.f;
                        Vec2 cones;
                        int32 type = 1;

                        Matrix directionalLight = Matrix();
                        directionalLight.m[0] = color.x;         directionalLight.m[1] = color.y;             directionalLight.m[2] = color.z;             directionalLight.m[3] = color.w;
                        directionalLight.m[4] = position.x;      directionalLight.m[5] = position.y;          directionalLight.m[6] = position.z;
                        directionalLight.m[7] = direction.x;     directionalLight.m[8] = direction.y;         directionalLight.m[9] = direction.z;
                        directionalLight.m[10] = attenuation;   //directionalLight.m[11] = attenuation.y;       directionalLight.m[12] = attenuation.z;
                        directionalLight.m[13] = cones.x;         directionalLight.m[14] = cones.y;
                        directionalLight.m[15] = type;

                        Lights.push_back(directionalLight);

                    } else if (PointLight* p = dynamic_cast<PointLight*>((*i))) {

                        // Point Lights
                        Vec4 color = p->GetLightColor();
                        Vec3 position = ViewMatrix * (p->GetOwner()->GetWorldPosition());
                        Vec3 direction;
                        f32 attenuation = p->GetLightRadius();
                        Vec2 cones;
                        int32 type = 2;

                        Matrix pointLight = Matrix();
                        pointLight.m[0] = color.x;       pointLight.m[1] = color.y;           pointLight.m[2] = color.z;           pointLight.m[3] = color.w;
                        pointLight.m[4] = position.x;    pointLight.m[5] = position.y;        pointLight.m[6] = position.z;
                        pointLight.m[7] = direction.x;   pointLight.m[8] = direction.y;       pointLight.m[9] = direction.z;
                        pointLight.m[10] = attenuation; //pointLight.m[11] = attenuation.y;     pointLight.m[12] = attenuation.z;
                        pointLight.m[13] = cones.x;       pointLight.m[14] = cones.y;
                        pointLight.m[15] = type;

                        Lights.push_back(pointLight);

                    } else if (SpotLight* s = dynamic_cast<SpotLight*>((*i))) {

                        // Spot Lights
                        Vec4 color = s->GetLightColor();
                        Vec3 position = ViewMatrix * (s->GetOwner()->GetWorldPosition());
                        Vec3 LDirection = s->GetLightDirection().normalize();
                        Vec4 direction = ViewMatrix * Vec4(LDirection.x,LDirection.y,LDirection.z,0.f);
                        f32 attenuation = s->GetLightRadius();
                        Vec2 cones = Vec2(s->GetLightCosInnerCone(),s->GetLightCosOutterCone());
                        int32 type = 3;

                        Matrix spotLight = Matrix();
                        spotLight.m[0] = color.x;        spotLight.m[1] = color.y;            spotLight.m[2] = color.z;            spotLight.m[3] = color.w;
                        spotLight.m[4] = position.x;     spotLight.m[5] = position.y;         spotLight.m[6] = position.z;
                        spotLight.m[7] = direction.x;    spotLight.m[8] = direction.y;        spotLight.m[9] = direction.z;
                        spotLight.m[10] = attenuation;  //spotLight.m[11] = attenuation.y;      spotLight.m[12] = attenuation.z;
                        spotLight.m[13] = cones.x;        spotLight.m[14] = cones.y;
                        spotLight.m[15] = type;

                        Lights.push_back(spotLight);
                    }
                }
            }

            // Save Time
            Timer = Scene->GetTime();

            // Update Lights Position and Direction to ViewSpace
            NumberOfLights = Lights.size();

            // Bind FBO
            fbo->Bind();

            for (uint32 i=0;i<6;i++)
            {
                // Clean View Matrix
                ViewMatrix.identity();

                // Create Light View Matrix For Rendering Each Face of the Cubemap
                if (i==0)
                    ViewMatrix.LookAt(Vec3::ZERO, Vec3(1.0, 0.0, 0.0), Vec3(0.0,-1.0,0.0)); // +X
                if (i==1)
                    ViewMatrix.LookAt(Vec3::ZERO, Vec3(-1.0, 0.0, 0.0), Vec3(0.0,-1.0,0.0)); // -X
                if (i==2)
                    ViewMatrix.LookAt(Vec3::ZERO, Vec3(0.0, 1.0, 0.0), Vec3(0.0,0.0,1.0)); // +Y
                if (i==3)
                    ViewMatrix.LookAt(Vec3::ZERO, Vec3(0.0, -1.0, 0.0), Vec3(0.0,0.0,-1.0)); // -Y
                if (i==4)
                    ViewMatrix.LookAt(Vec3::ZERO, Vec3(0.0, 0.0, 1.0), Vec3(0.0,-1.0,0.0)); // +Z
                if (i==5)
                    ViewMatrix.LookAt(Vec3::ZERO, Vec3(0.0, 0.0, -1.0), Vec3(0.0,-1.0,0.0)); // -Z

                // Translate Light View Matrix
                ViewMatrix*=AllSeeingEye->GetWorldTransformation().Inverse();

                // Frame Buffer Attachment
                fbo->AddAttach(FrameBufferAttachmentFormat::Color_Attachment0,TextureType::CubemapPositive_X+i,environmentMap);

                // Set Viewport
                SetViewPort(0,0, Width, Height);

                // Clear Screen
                ClearScreen(Buffer_Bit::Color | Buffer_Bit::Depth);
                SetBackground(Vec4::ZERO);
                EnableDepthTest();

                // Update Culling
                UpdateCulling(ProjectionMatrix*ViewMatrix);

                // Render Scene with Objects Material
                for (std::vector<RenderingMesh*>::iterator k=rmesh.begin();k!=rmesh.end();k++)
                {

                    if ((*k)->renderingComponent->GetOwner()!=NULL)
                    {
                        // Culling Test
                        bool cullingTest = false;
                        switch((*k)->CullingGeometry)
                        {
                            case CullingGeometry::Box:
                                cullingTest = CullingBoxTest(*k);
                                break;
                            case CullingGeometry::Sphere:
                            default:
                                cullingTest = CullingSphereTest(*k);
                                break;
                        }
                        if (cullingTest && (*k)->renderingComponent->IsActive())
                            RenderObject((*k),(*k)->Material);
                    }
                }
            }

            fbo->UnBind();

            EndRender();
        }
    }

    Texture* CubemapRenderer::GetTexture()
    {
        return environmentMap;
    }

};<|endoftext|>


<commit_before>#include "stan/math/functions/binomial_coefficient_log.hpp"
#include <gtest/gtest.h>

TEST(MathFunctions, binomial_coefficient_log) {
  using stan::math::binomial_coefficient_log;
  EXPECT_FLOAT_EQ(1.0, exp(binomial_coefficient_log(2.0,2.0)));
  EXPECT_FLOAT_EQ(2.0, exp(binomial_coefficient_log(2.0,1.0)));
  EXPECT_FLOAT_EQ(3.0, exp(binomial_coefficient_log(3.0,1.0)));
  EXPECT_NEAR(3.0, exp(binomial_coefficient_log(3.0,2.0)),0.0001);
}
<commit_msg>added NaN test for binomial_coefficient_log<commit_after>#include <stan/math/functions/binomial_coefficient_log.hpp>
#include <boost/math/special_functions/fpclassify.hpp>
#include <gtest/gtest.h>

TEST(MathFunctions, binomial_coefficient_log) {
  using stan::math::binomial_coefficient_log;
  EXPECT_FLOAT_EQ(1.0, exp(binomial_coefficient_log(2.0,2.0)));
  EXPECT_FLOAT_EQ(2.0, exp(binomial_coefficient_log(2.0,1.0)));
  EXPECT_FLOAT_EQ(3.0, exp(binomial_coefficient_log(3.0,1.0)));
  EXPECT_NEAR(3.0, exp(binomial_coefficient_log(3.0,2.0)),0.0001);
}

TEST(MathFunctions, binomial_coefficient_log_nan) {
  double nan = std::numeric_limits<double>::quiet_NaN();

  EXPECT_PRED1(boost::math::isnan<double>,
               stan::math::binomial_coefficient_log(2.0, nan));
  EXPECT_PRED1(boost::math::isnan<double>,
               stan::math::binomial_coefficient_log(nan, 2.0));
  EXPECT_PRED1(boost::math::isnan<double>,
               stan::math::binomial_coefficient_log(nan, nan));
}
<|endoftext|>