<commit_before>#pragma once

#include "Communicator.hpp"
#include "CompletionEvent.hpp"
#include "Tasking.hpp"
#include "Message.hpp"
#include "MessagePool.hpp"
#include "Delegate.hpp"
#include "Collective.hpp"
#include "Timestamp.hpp"
#include <type_traits>

namespace Grappa {

/// GlobalCompletionEvent (GCE):
/// Synchronization construct for determining when a global phase of asynchronous tasks have all completed.
/// For example, can be used to ensure that all tasks of a parallel loop have completed, including tasks or asynchronous delegates spawned during execution of the parallel loop.
///
/// A GlobalCompletionEvent must be replicated at the same address on all cores (the easiest way is to declare it as file-global or static storage).
///
/// Anyone calling "wait" after at least some work has been "enrolled" globally will block. When *all* work has been completed on all cores, all tasks waiting on the GCE will be woken.
///
/// To ensure consistent behavior and guarantee deadlock freedom, every "enroll" must be causally followed by "complete", so either must be completed from the same task that called "enroll" or from a task spawned (transitively) from the enrolling task.
class GlobalCompletionEvent : public CompletionEvent {
  // All nodes
  // (count)
  // (cv)
  bool event_in_progress;
  Core master_core;

  // Master barrier only
  Core cores_out;

  /// pointer to shared arg for loops that use a GCE
  const void * shared_ptr;

public:

  GlobalCompletionEvent(): master_core(0) { reset(); }

  inline void set_shared_ptr(const void* p) { shared_ptr = p; }
  template<typename T> inline const T* get_shared_ptr() { return reinterpret_cast<const T*>(shared_ptr); }

  /// SPMD (either all cores call this following a barrier, or use `reset_all` from one task,
  /// then spawn parallel work)
  void reset() {
    count = 0;
    cv.waiters_ = 0;
    cores_out = 0;
    event_in_progress = false;
  }

  /// Called from single task (probably `user_main`).
  void reset_all() {
    call_on_all_cores([this]{ reset(); });
  }

  /// Enroll more things that need to be completed before the global completion is, well, complete.
  /// This will send a cancel to the master if this core previously entered the cancellable barrier.
  ///
  /// Blocks until cancel completes (if it must cancel) to ensure correct ordering, therefore
  /// cannot be called from message handler (but I don't think we ever do).
  void enroll(int64_t inc = 1) {
    if (inc == 0) return;

    CHECK_GE(inc, 1);
    count += inc;

    // first one to have work here
    if (count == inc) { // count[0 -> inc]
      event_in_progress = true; // optimization to save checking in wait()
      // cancel barrier
      Core co = delegate::call(master_core, [this] {
        cores_out++;
        return cores_out;
      });
      // first one to cancel barrier should make sure other cores are ready to wait
      if (co == 1) { // cores_out[0 -> 1]
        event_in_progress = true;
        call_on_all_cores([this] {
          event_in_progress = true;
        });
        CHECK(event_in_progress);
      }
      // block until cancelled
      CHECK_GT(count, 0);
      VLOG(2) << "cores_out: " << co << ", count: " << count;
    }
  }

  /// Mark a certain number of things completed. When the global count on all cores goes to 0, all
  /// tasks waiting on the GCE will be woken.
  ///
  /// Note: this can be called in a message handler (e.g. remote completes from stolen tasks).
  void complete(int64_t dec = 1) {
    count -= dec;
    DVLOG(4) << "complete (" << count << ") -- " << this;

    // out of work here
    if (count == 0) { // count[dec -> 0]
      // enter cancellable barrier
      send_heap_message(master_core, [this] {
        cores_out--;

        // if all are in
        if (cores_out == 0) { // cores_out[1 -> 0]
          CHECK_EQ(count, 0);
          // notify everyone to wake
          for (Core c = 0; c < cores(); c++) {
            send_heap_message(c, [this] {
              CHECK_EQ(count, 0);
              broadcast(&cv); // wake anyone who was waiting here
              reset(); // reset, now anyone else calling `wait` should fall through
            });
          }
        }
      });
    }
  }

  void wait() {
    VLOG(3) << "wait(): event_in_progress: " << event_in_progress << ", count: " << count;
    if (event_in_progress) {
      Grappa::wait(&cv);
    } else {
      // conservative check, in case we're calling `wait` without calling `enroll`
      if (delegate::call(master_core, [this]{ return cores_out; }) > 0) {
//      if (delegate::call(master_core, [this]{ return event_in_progress; })) {
        Grappa::wait(&cv);
        VLOG(3) << "woke from conservative check";
      }
      VLOG(3) << "fell thru conservative check";
    }
    CHECK(!event_in_progress);
    CHECK_EQ(count, 0);
  }

};

} // namespace Grappa

/// Synchronizing delegates
namespace Grappa {
  /// Synchronizing private task spawn. Automatically enrolls task with GlobalCompletionEvent and
  /// does local `complete` when done (if GCE is non-null).
  template<typename TF>
  void privateTask(GlobalCompletionEvent * gce, TF tf) {
    gce->enroll();
    privateTask([gce,tf] {
      tf();
      gce->complete();
    });
  }

  /// Synchronizing public task spawn. Automatically enrolls task with GlobalCompletionEvent and
  /// sends `complete`  message when done (if GCE is non-null).
  template<GlobalCompletionEvent * GCE, typename TF>
  inline void publicTask(TF tf) {
    if (GCE) GCE->enroll();
    Core origin = mycore();
    publicTask([origin,tf] {
      tf();
      if (GCE) complete(make_global(GCE,origin));
    });
  }
} // namespace Grappa
<commit_msg>add possible assertion to GCE<commit_after>#pragma once

#include "Communicator.hpp"
#include "CompletionEvent.hpp"
#include "Tasking.hpp"
#include "Message.hpp"
#include "MessagePool.hpp"
#include "Delegate.hpp"
#include "Collective.hpp"
#include "Timestamp.hpp"
#include <type_traits>

namespace Grappa {

/// GlobalCompletionEvent (GCE):
/// Synchronization construct for determining when a global phase of asynchronous tasks have all completed.
/// For example, can be used to ensure that all tasks of a parallel loop have completed, including tasks or asynchronous delegates spawned during execution of the parallel loop.
///
/// A GlobalCompletionEvent must be replicated at the same address on all cores (the easiest way is to declare it as file-global or static storage).
///
/// Anyone calling "wait" after at least some work has been "enrolled" globally will block. When *all* work has been completed on all cores, all tasks waiting on the GCE will be woken.
///
/// To ensure consistent behavior and guarantee deadlock freedom, every "enroll" must be causally followed by "complete", so either must be completed from the same task that called "enroll" or from a task spawned (transitively) from the enrolling task.
class GlobalCompletionEvent : public CompletionEvent {
  // All nodes
  // (count)
  // (cv)
  bool event_in_progress;
  Core master_core;

  // Master barrier only
  Core cores_out;

  /// pointer to shared arg for loops that use a GCE
  const void * shared_ptr;

public:

  GlobalCompletionEvent(): master_core(0) { reset(); }

  inline void set_shared_ptr(const void* p) { shared_ptr = p; }
  template<typename T> inline const T* get_shared_ptr() { return reinterpret_cast<const T*>(shared_ptr); }

  /// SPMD (either all cores call this following a barrier, or use `reset_all` from one task,
  /// then spawn parallel work)
  void reset() {
    count = 0;
    cv.waiters_ = 0;
    cores_out = 0;
    event_in_progress = false;
  }

  /// Called from single task (probably `user_main`).
  void reset_all() {
    call_on_all_cores([this]{ reset(); });
  }

  /// Enroll more things that need to be completed before the global completion is, well, complete.
  /// This will send a cancel to the master if this core previously entered the cancellable barrier.
  ///
  /// Blocks until cancel completes (if it must cancel) to ensure correct ordering, therefore
  /// cannot be called from message handler (but I don't think we ever do).
  void enroll(int64_t inc = 1) {
    if (inc == 0) return;

    CHECK_GE(inc, 1);
    count += inc;

    // first one to have work here
    if (count == inc) { // count[0 -> inc]
      event_in_progress = true; // optimization to save checking in wait()
      // cancel barrier
      Core co = delegate::call(master_core, [this] {
        cores_out++;
        return cores_out;
      });
      // first one to cancel barrier should make sure other cores are ready to wait
      if (co == 1) { // cores_out[0 -> 1]
        event_in_progress = true;
        call_on_all_cores([this] {
          event_in_progress = true;
        });
        CHECK(event_in_progress);
      }
      // block until cancelled
      CHECK_GT(count, 0);
      CHECK_LE(cores_out, Grappa::cores()+1); // allowed one extra?
      VLOG(2) << "cores_out: " << co << ", count: " << count;
    }
  }

  /// Mark a certain number of things completed. When the global count on all cores goes to 0, all
  /// tasks waiting on the GCE will be woken.
  ///
  /// Note: this can be called in a message handler (e.g. remote completes from stolen tasks).
  void complete(int64_t dec = 1) {
    count -= dec;
    DVLOG(4) << "complete (" << count << ") -- " << this;

    // out of work here
    if (count == 0) { // count[dec -> 0]
      // enter cancellable barrier
      send_heap_message(master_core, [this] {
        cores_out--;

        // if all are in
        if (cores_out == 0) { // cores_out[1 -> 0]
          CHECK_EQ(count, 0);
          // notify everyone to wake
          for (Core c = 0; c < cores(); c++) {
            send_heap_message(c, [this] {
              CHECK_EQ(count, 0);
              broadcast(&cv); // wake anyone who was waiting here
              reset(); // reset, now anyone else calling `wait` should fall through
            });
          }
        }
      });
    }
  }

  void wait() {
    VLOG(3) << "wait(): event_in_progress: " << event_in_progress << ", count: " << count;
    if (event_in_progress) {
      Grappa::wait(&cv);
    } else {
      // conservative check, in case we're calling `wait` without calling `enroll`
      if (delegate::call(master_core, [this]{ return cores_out; }) > 0) {
//      if (delegate::call(master_core, [this]{ return event_in_progress; })) {
        Grappa::wait(&cv);
        VLOG(3) << "woke from conservative check";
      }
      VLOG(3) << "fell thru conservative check";
    }
    CHECK(!event_in_progress);
    CHECK_EQ(count, 0);
  }

};

} // namespace Grappa

/// Synchronizing delegates
namespace Grappa {
  /// Synchronizing private task spawn. Automatically enrolls task with GlobalCompletionEvent and
  /// does local `complete` when done (if GCE is non-null).
  template<typename TF>
  void privateTask(GlobalCompletionEvent * gce, TF tf) {
    gce->enroll();
    privateTask([gce,tf] {
      tf();
      gce->complete();
    });
  }

  /// Synchronizing public task spawn. Automatically enrolls task with GlobalCompletionEvent and
  /// sends `complete`  message when done (if GCE is non-null).
  template<GlobalCompletionEvent * GCE, typename TF>
  inline void publicTask(TF tf) {
    if (GCE) GCE->enroll();
    Core origin = mycore();
    publicTask([origin,tf] {
      tf();
      if (GCE) complete(make_global(GCE,origin));
    });
  }
} // namespace Grappa
<|endoftext|>


<commit_before>/*=========================================================================

Program:   Medical Imaging & Interaction Toolkit
Language:  C++
Date:      $Date: 2010-03-31 16:40:27 +0200 (Mi, 31 Mrz 2010) $
Version:   $Revision: 16011 $

Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.

This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.  See the above copyright notices for more information.

=========================================================================*/

#include "mitkNavigationDataToOpenGLFilter.h"
#include <mitkVector.h>

mitk::NavigationDataToOpenGLFilter::NavigationDataToOpenGLFilter()
  : mitk::NavigationDataToNavigationDataFilter()
{
}

mitk::NavigationDataToOpenGLFilter::~NavigationDataToOpenGLFilter()
{
}

void mitk::NavigationDataToOpenGLFilter::GenerateData()
{
  this->CreateOutputsForAllInputs(); // make sure that we have the same number of outputs as inputs

  /* update outputs with tracking data from tools */
  unsigned int numberOfOutputs = this->GetNumberOfOutputs();
  for (unsigned int i = 0; i < numberOfOutputs ; ++i)
  {
    mitk::NavigationData* output = this->GetOutput(i);
    assert(output);
    const mitk::NavigationData* input = this->GetInput(i);
    assert(input);

    if (input->IsDataValid() == false || input->GetHasOrientation()
      || input->GetHasOrientation())
    {
      MITK_WARN("mitk::NavigationDataToOpenGLFilter::GenerateData()")
        << "Input Navigation Data is either invalid or has no position or "
        << "has no orientation.";
      continue;
    }

    output->Graft(input); // First, copy all information from input to output

    vnl_matrix<mitk::ScalarType> vnlRotation(
      input->GetOrientation().rotation_matrix_transpose());

    // normalize rows of rotation matrix
    vnlRotation.normalize_rows();

    vnl_matrix<mitk::ScalarType> vnlInverseRotation;
    vnlInverseRotation.set_size(3,3);
    // invert rotation
    vnlInverseRotation = vnl_matrix_inverse<mitk::ScalarType>(vnlRotation);

    vnl_vector<mitk::ScalarType> vnlTranslation = input->GetPosition().GetVnlVector();
    // rotate translation vector by inverse rotation P = P'
    vnlTranslation    = vnlInverseRotation * vnlTranslation;
    vnlTranslation    *= -1;  // save -P'

    // set new translation and rotation on output navdata objects
    mitk::Point3D position;
    mitk::FillVector3D(position, vnlTranslation[0], vnlTranslation[1], vnlTranslation[2]);
    output->SetPosition( position ); // set position
    output->SetOrientation( mitk::Quaternion( vnlRotation ) );
  }
}<commit_msg>ENH (#3262): various bugfixes, finished IGT pipeline classes for inside out tracking (tested)<commit_after>/*=========================================================================

Program:   Medical Imaging & Interaction Toolkit
Language:  C++
Date:      $Date: 2010-03-31 16:40:27 +0200 (Mi, 31 Mrz 2010) $
Version:   $Revision: 16011 $

Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.

This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.  See the above copyright notices for more information.

=========================================================================*/

#include "mitkNavigationDataToOpenGLFilter.h"
#include <mitkVector.h>

mitk::NavigationDataToOpenGLFilter::NavigationDataToOpenGLFilter()
  : mitk::NavigationDataToNavigationDataFilter()
{
}

mitk::NavigationDataToOpenGLFilter::~NavigationDataToOpenGLFilter()
{
}

void mitk::NavigationDataToOpenGLFilter::GenerateData()
{
  this->CreateOutputsForAllInputs(); // make sure that we have the same number of outputs as inputs

  /* update outputs with tracking data from tools */
  unsigned int numberOfOutputs = this->GetNumberOfOutputs();
  for (unsigned int i = 0; i < numberOfOutputs ; ++i)
  {
    mitk::NavigationData* output = this->GetOutput(i);
    assert(output);
    const mitk::NavigationData* input = this->GetInput(i);
    assert(input);

    if (input->IsDataValid() == false || !input->GetHasOrientation()
      || !input->GetHasOrientation())
    {
      MITK_WARN("mitk::NavigationDataToOpenGLFilter::GenerateData()")
        << "Input Navigation Data is either invalid or has no position or "
        << "has no orientation.";
      continue;
    }

    /*
    vnl_vector<mitk::ScalarType> vnlTranslation
        = input->GetPosition().GetVnlVector();

    vnl_matrix<mitk::ScalarType> vnlRotation(
      input->GetOrientation().rotation_matrix_transpose());

    vnl_matrix_fixed<mitk::ScalarType, 4, 4> m;
    m.fill(0);
    m(3,3) = 1;
    m.update(vnlRotation);
    m.set_column(3, vnlTranslation);
    MITK_DEBUG << "left handed matrix: " << m;

    // switch to right/left handed
    m[1][0] = -m[1][0];
    m[1][1] = -m[1][1];
    m[1][2] = -m[1][2];
    m[1][3] = -m[1][3];
    m[2][0] = -m[2][0];
    m[2][1] = -m[2][1];
    m[2][2] = -m[2][2];
    m[2][3] = -m[2][3];

    MITK_DEBUG << "right handed matrix: " << m;

    vnlTranslation = m.get_column(3);
    vnlTranslation = vnlTranslation.extract(3);
    vnlRotation = m.extract(3, 3);

    output->SetPosition( mitk::Point3D( vnlTranslation.data_block() ) );
    output->SetOrientation( vnl_quaternion<mitk::ScalarType> ( vnlRotation ) );
    */

    output->Graft(input); // First, copy all information from input to output

    vnl_matrix<mitk::ScalarType> vnlRotation(
      input->GetOrientation().rotation_matrix_transpose());

    // normalize rows of rotation matrix
    vnlRotation.normalize_rows();

    vnl_matrix<mitk::ScalarType> vnlInverseRotation(3,3);
    // invert rotation
    vnlInverseRotation = vnl_matrix_inverse<mitk::ScalarType>(vnlRotation);

    vnl_vector<mitk::ScalarType> vnlTranslation
        = input->GetPosition().GetVnlVector();
    // rotate translation vector by inverse rotation P = P'
    vnlTranslation = vnlInverseRotation * vnlTranslation;
    vnlTranslation *= -1;  // save -P'

    // set new translation and rotation on output navdata objects
    mitk::Point3D position;
    mitk::FillVector3D(position,
                       vnlTranslation[0],
                       vnlTranslation[1],
                       vnlTranslation[2]);

    // set position
    output->SetPosition( mitk::Point3D( vnlTranslation.data_block() ) );
    output->SetOrientation( mitk::Quaternion( vnlRotation ) );

  }
}
<|endoftext|>


<commit_before>/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * Copyright (C) 2012 Sergey Lisitsyn
 */

#include <shogun/transfer/multitask/MultitaskCompositeMachine.h>

#include <map>
#include <vector>

using namespace std;

namespace shogun
{

CMultitaskCompositeMachine::CMultitaskCompositeMachine() :
	CMachine(), m_machine(NULL), m_features(NULL), m_current_task(0),
	m_task_group(NULL)
{
	register_parameters();
}

CMultitaskCompositeMachine::CMultitaskCompositeMachine(
     CMachine* machine, CFeatures* train_features,
     CLabels* train_labels, CTaskGroup* task_group) :
	CMachine(), m_machine(NULL), m_features(NULL),
	m_current_task(0), m_task_group(NULL)
{
	set_machine(machine);
	set_features(train_features);
	set_labels(train_labels);
	set_task_group(task_group);
	register_parameters();
}

CMultitaskCompositeMachine::~CMultitaskCompositeMachine()
{
	SG_UNREF(m_machine);
	SG_UNREF(m_features);
	SG_UNREF(m_task_machines);
	SG_UNREF(m_task_group);
}

void CMultitaskCompositeMachine::register_parameters()
{
	SG_ADD((CSGObject**)&m_machine, "machine", "machine", MS_AVAILABLE);
	SG_ADD((CSGObject**)&m_features, "features", "features", MS_NOT_AVAILABLE);
	SG_ADD((CSGObject**)&m_task_machines, "task_machines", "task machines", MS_NOT_AVAILABLE);
	SG_ADD((CSGObject**)&m_task_group, "task_group", "task group", MS_NOT_AVAILABLE);
}

int32_t CMultitaskCompositeMachine::get_current_task() const
{
	return m_current_task;
}

void CMultitaskCompositeMachine::set_current_task(int32_t task)
{
	m_current_task = task;
}

CTaskGroup* CMultitaskCompositeMachine::get_task_group() const
{
	SG_REF(m_task_group);
	return m_task_group;
}

void CMultitaskCompositeMachine::set_task_group(CTaskGroup* task_group)
{
	SG_UNREF(m_task_group);
	SG_REF(task_group);
	m_task_group = task_group;
}

bool CMultitaskCompositeMachine::train_machine(CFeatures* data)
{
	SG_NOTIMPLEMENTED;
	return false;
}

void CMultitaskCompositeMachine::post_lock(CLabels* labels, CFeatures* features)
{
	set_features(m_features);
	m_machine->data_lock(labels,features);

	int n_tasks = m_task_group->get_num_tasks();
	SGVector<index_t>* tasks_indices = m_task_group->get_tasks_indices();

	m_tasks_indices.clear();
	for (int32_t i=0; i<n_tasks; i++)
	{
		set<index_t> indices_set;
		SGVector<index_t> task_indices = tasks_indices[i];
		for (int32_t j=0; j<task_indices.vlen; j++)
			indices_set.insert(task_indices[j]);

		m_tasks_indices.push_back(indices_set);
	}

	for (int32_t i=0; i<n_tasks; i++)
		tasks_indices[i].~SGVector<index_t>();
	SG_FREE(tasks_indices);
}

bool CMultitaskCompositeMachine::train_locked(SGVector<index_t> indices)
{
	int n_tasks = m_task_group->get_num_tasks();
	ASSERT((int)m_tasks_indices.size()==n_tasks);
	vector< vector<index_t> > cutted_task_indices;
	for (int32_t i=0; i<n_tasks; i++)
		cutted_task_indices.push_back(vector<index_t>());
	for (int32_t i=0; i<indices.vlen; i++)
	{
		for (int32_t j=0; j<n_tasks; j++)
		{
			if (m_tasks_indices[j].count(indices[i]))
			{
				cutted_task_indices[j].push_back(indices[i]);
				break;
			}
		}
	}
	SGVector<index_t> task_indices(n_tasks);
	SG_UNREF(m_task_machines);
	m_task_machines = new CDynamicObjectArray();
	for (int32_t i=0; i<n_tasks; i++)
	{
		for (int32_t j=0; j<(int)cutted_task_indices[i].size(); j++)
			task_indices[j] = cutted_task_indices[i][j];

		m_features->add_subset(task_indices);
		m_labels->add_subset(task_indices);
		m_machine->train(m_features);
		m_features->remove_subset();
		m_labels->remove_subset();
		m_task_machines->push_back(m_machine->clone());
	}
	return true;
}

float64_t CMultitaskCompositeMachine::apply_one(int32_t i)
{
	CMachine* m = (CMachine*)(m_task_machines->get_element(m_current_task));
	float64_t result = m->apply_one(i);
	SG_UNREF(m);
	return result;
}

CBinaryLabels* CMultitaskCompositeMachine::apply_locked_binary(SGVector<index_t> indices)
{
	int n_tasks = m_task_group->get_num_tasks();
	SGVector<float64_t> result(indices.vlen);
	result.zero();
	for (int32_t i=0; i<indices.vlen; i++)
	{
		for (int32_t j=0; j<n_tasks; j++)
		{
			if (m_tasks_indices[j].count(indices[i]))
			{
				set_current_task(j);
				result[i] = apply_one(indices[i]);
				break;
			}
		}
	}
	return new CBinaryLabels(result);
}

}
<commit_msg>Fixed MultitaskCompositeMachine train locked<commit_after>/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * Copyright (C) 2012 Sergey Lisitsyn
 */

#include <shogun/transfer/multitask/MultitaskCompositeMachine.h>

#include <map>
#include <vector>

using namespace std;

namespace shogun
{

CMultitaskCompositeMachine::CMultitaskCompositeMachine() :
	CMachine(), m_machine(NULL), m_features(NULL), m_current_task(0),
	m_task_group(NULL)
{
	register_parameters();
}

CMultitaskCompositeMachine::CMultitaskCompositeMachine(
     CMachine* machine, CFeatures* train_features,
     CLabels* train_labels, CTaskGroup* task_group) :
	CMachine(), m_machine(NULL), m_features(NULL),
	m_current_task(0), m_task_group(NULL)
{
	set_machine(machine);
	set_features(train_features);
	set_labels(train_labels);
	set_task_group(task_group);
	register_parameters();
}

CMultitaskCompositeMachine::~CMultitaskCompositeMachine()
{
	SG_UNREF(m_machine);
	SG_UNREF(m_features);
	SG_UNREF(m_task_machines);
	SG_UNREF(m_task_group);
}

void CMultitaskCompositeMachine::register_parameters()
{
	SG_ADD((CSGObject**)&m_machine, "machine", "machine", MS_AVAILABLE);
	SG_ADD((CSGObject**)&m_features, "features", "features", MS_NOT_AVAILABLE);
	SG_ADD((CSGObject**)&m_task_machines, "task_machines", "task machines", MS_NOT_AVAILABLE);
	SG_ADD((CSGObject**)&m_task_group, "task_group", "task group", MS_NOT_AVAILABLE);
}

int32_t CMultitaskCompositeMachine::get_current_task() const
{
	return m_current_task;
}

void CMultitaskCompositeMachine::set_current_task(int32_t task)
{
	m_current_task = task;
}

CTaskGroup* CMultitaskCompositeMachine::get_task_group() const
{
	SG_REF(m_task_group);
	return m_task_group;
}

void CMultitaskCompositeMachine::set_task_group(CTaskGroup* task_group)
{
	SG_UNREF(m_task_group);
	SG_REF(task_group);
	m_task_group = task_group;
}

bool CMultitaskCompositeMachine::train_machine(CFeatures* data)
{
	SG_NOTIMPLEMENTED;
	return false;
}

void CMultitaskCompositeMachine::post_lock(CLabels* labels, CFeatures* features)
{
	ASSERT(m_task_group);
	set_features(m_features);
	if (!m_machine->is_data_locked())
		m_machine->data_lock(labels,features);

	int n_tasks = m_task_group->get_num_tasks();
	SGVector<index_t>* tasks_indices = m_task_group->get_tasks_indices();

	m_tasks_indices.clear();
	for (int32_t i=0; i<n_tasks; i++)
	{
		set<index_t> indices_set;
		SGVector<index_t> task_indices = tasks_indices[i];
		for (int32_t j=0; j<task_indices.vlen; j++)
			indices_set.insert(task_indices[j]);

		m_tasks_indices.push_back(indices_set);
	}

	for (int32_t i=0; i<n_tasks; i++)
		tasks_indices[i].~SGVector<index_t>();
	SG_FREE(tasks_indices);
}

bool CMultitaskCompositeMachine::train_locked(SGVector<index_t> indices)
{
	int n_tasks = m_task_group->get_num_tasks();
	ASSERT((int)m_tasks_indices.size()==n_tasks);
	vector< vector<index_t> > cutted_task_indices;
	for (int32_t i=0; i<n_tasks; i++)
		cutted_task_indices.push_back(vector<index_t>());
	for (int32_t i=0; i<indices.vlen; i++)
	{
		for (int32_t j=0; j<n_tasks; j++)
		{
			if (m_tasks_indices[j].count(indices[i]))
			{
				cutted_task_indices[j].push_back(indices[i]);
				break;
			}
		}
	}
	//SG_UNREF(m_task_machines);
	m_task_machines = new CDynamicObjectArray();
	for (int32_t i=0; i<n_tasks; i++)
	{
		SGVector<index_t> task_indices(cutted_task_indices[i].size());
		for (int32_t j=0; j<(int)cutted_task_indices[i].size(); j++)
			task_indices[j] = cutted_task_indices[i][j];

		m_machine->train_locked(task_indices);
		m_task_machines->push_back(m_machine->clone());
	}
	return true;
}

float64_t CMultitaskCompositeMachine::apply_one(int32_t i)
{
	CMachine* m = (CMachine*)(m_task_machines->get_element(m_current_task));
	float64_t result = m->apply_one(i);
	SG_UNREF(m);
	return result;
}

CBinaryLabels* CMultitaskCompositeMachine::apply_locked_binary(SGVector<index_t> indices)
{
	int n_tasks = m_task_group->get_num_tasks();
	SGVector<float64_t> result(indices.vlen);
	result.zero();
	for (int32_t i=0; i<indices.vlen; i++)
	{
		for (int32_t j=0; j<n_tasks; j++)
		{
			if (m_tasks_indices[j].count(indices[i]))
			{
				set_current_task(j);
				result[i] = apply_one(indices[i]);
				break;
			}
		}
	}
	return new CBinaryLabels(result);
}

}
<|endoftext|>


<commit_before>/*
 * Copyright © 2012 Intel Corporation
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice (including the next
 * paragraph) shall be included in all copies or substantial portions of the
 * Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 * IN THE SOFTWARE.
 *
 * Authors:
 *    Eric Anholt <eric@anholt.net>
 *
 */

#include "brw_cfg.h"
#include "brw_fs_live_variables.h"

using namespace brw;

#define MAX_INSTRUCTION (1 << 30)

/** @file brw_fs_live_variables.cpp
 *
 * Support for calculating liveness information about virtual GRFs.
 *
 * This produces a live interval for each whole virtual GRF.  We could
 * choose to expose per-component live intervals for VGRFs of size > 1,
 * but we currently do not.  It is easier for the consumers of this
 * information to work with whole VGRFs.
 *
 * However, we internally track use/def information at the per-component
 * (reg_offset) level for greater accuracy.  Large VGRFs may be accessed
 * piecemeal over many (possibly non-adjacent) instructions.  In this case,
 * examining a single instruction is insufficient to decide whether a whole
 * VGRF is ultimately used or defined.  Tracking individual components
 * allows us to easily assemble this information.
 *
 * See Muchnick's Advanced Compiler Design and Implementation, section
 * 14.1 (p444).
 */

void
fs_live_variables::setup_one_read(bblock_t *block, fs_inst *inst,
                                  int ip, fs_reg reg)
{
   int var = var_from_vgrf[reg.reg] + reg.reg_offset;
   assert(var < num_vars);

   /* In most cases, a register can be written over safely by the
    * same instruction that is its last use.  For a single
    * instruction, the sources are dereferenced before writing of the
    * destination starts (naturally).  This gets more complicated for
    * simd16, because the instruction:
    *
    * add(16)      g4<1>F      g4<8,8,1>F   g6<8,8,1>F
    *
    * is actually decoded in hardware as:
    *
    * add(8)       g4<1>F      g4<8,8,1>F   g6<8,8,1>F
    * add(8)       g5<1>F      g5<8,8,1>F   g7<8,8,1>F
    *
    * Which is safe.  However, if we have uniform accesses
    * happening, we get into trouble:
    *
    * add(8)       g4<1>F      g4<0,1,0>F   g6<8,8,1>F
    * add(8)       g5<1>F      g4<0,1,0>F   g7<8,8,1>F
    *
    * Now our destination for the first instruction overwrote the
    * second instruction's src0, and we get garbage for those 8
    * pixels.  There's a similar issue for the pre-gen6
    * pixel_x/pixel_y, which are registers of 16-bit values and thus
    * would get stomped by the first decode as well.
    */
   int end_ip = ip;
   if (v->dispatch_width == 16 && (reg.stride == 0 ||
                                   reg.type == BRW_REGISTER_TYPE_UW ||
                                   reg.type == BRW_REGISTER_TYPE_W ||
                                   reg.type == BRW_REGISTER_TYPE_UB ||
                                   reg.type == BRW_REGISTER_TYPE_B)) {
      end_ip++;
   }

   start[var] = MIN2(start[var], ip);
   end[var] = MAX2(end[var], end_ip);

   /* The use[] bitset marks when the block makes use of a variable (VGRF
    * channel) without having completely defined that variable within the
    * block.
    */
   if (!BITSET_TEST(bd[block->num].def, var))
      BITSET_SET(bd[block->num].use, var);
}

void
fs_live_variables::setup_one_write(bblock_t *block, fs_inst *inst,
                                   int ip, fs_reg reg)
{
   int var = var_from_vgrf[reg.reg] + reg.reg_offset;
   assert(var < num_vars);

   start[var] = MIN2(start[var], ip);
   end[var] = MAX2(end[var], ip);

   /* The def[] bitset marks when an initialization in a block completely
    * screens off previous updates of that variable (VGRF channel).
    */
   if (inst->dst.file == GRF && !inst->is_partial_write()) {
      if (!BITSET_TEST(bd[block->num].use, var))
         BITSET_SET(bd[block->num].def, var);
   }
}

/**
 * Sets up the use[] and def[] bitsets.
 *
 * The basic-block-level live variable analysis needs to know which
 * variables get used before they're completely defined, and which
 * variables are completely defined before they're used.
 *
 * These are tracked at the per-component level, rather than whole VGRFs.
 */
void
fs_live_variables::setup_def_use()
{
   int ip = 0;

   foreach_block (block, cfg) {
      assert(ip == block->start_ip);
      if (block->num > 0)
	 assert(cfg->blocks[block->num - 1]->end_ip == ip - 1);

      foreach_inst_in_block(fs_inst, inst, block) {
	 /* Set use[] for this instruction */
	 for (unsigned int i = 0; i < inst->sources; i++) {
            fs_reg reg = inst->src[i];

            if (reg.file != GRF)
               continue;

            for (int j = 0; j < inst->regs_read(v, i); j++) {
               setup_one_read(block, inst, ip, reg);
               reg.reg_offset++;
            }
	 }

         /* Set def[] for this instruction */
         if (inst->dst.file == GRF) {
            fs_reg reg = inst->dst;
            for (int j = 0; j < inst->regs_written; j++) {
               setup_one_write(block, inst, ip, reg);
               reg.reg_offset++;
            }
	 }

	 ip++;
      }
   }
}

/**
 * The algorithm incrementally sets bits in liveout and livein,
 * propagating it through control flow.  It will eventually terminate
 * because it only ever adds bits, and stops when no bits are added in
 * a pass.
 */
void
fs_live_variables::compute_live_variables()
{
   bool cont = true;

   while (cont) {
      cont = false;

      foreach_block (block, cfg) {
	 /* Update livein */
	 for (int i = 0; i < bitset_words; i++) {
            BITSET_WORD new_livein = (bd[block->num].use[i] |
                                      (bd[block->num].liveout[i] &
                                       ~bd[block->num].def[i]));
	    if (new_livein & ~bd[block->num].livein[i]) {
               bd[block->num].livein[i] |= new_livein;
               cont = true;
	    }
	 }

	 /* Update liveout */
	 foreach_list_typed(bblock_link, child_link, link, &block->children) {
	    bblock_t *child = child_link->block;

	    for (int i = 0; i < bitset_words; i++) {
               BITSET_WORD new_liveout = (bd[child->num].livein[i] &
                                          ~bd[block->num].liveout[i]);
               if (new_liveout) {
                  bd[block->num].liveout[i] |= new_liveout;
                  cont = true;
               }
	    }
	 }
      }
   }
}

/**
 * Extend the start/end ranges for each variable to account for the
 * new information calculated from control flow.
 */
void
fs_live_variables::compute_start_end()
{
   foreach_block (block, cfg) {
      for (int i = 0; i < num_vars; i++) {
	 if (BITSET_TEST(bd[block->num].livein, i)) {
	    start[i] = MIN2(start[i], block->start_ip);
	    end[i] = MAX2(end[i], block->start_ip);
	 }

	 if (BITSET_TEST(bd[block->num].liveout, i)) {
	    start[i] = MIN2(start[i], block->end_ip);
	    end[i] = MAX2(end[i], block->end_ip);
	 }

      }
   }
}

int
fs_live_variables::var_from_reg(fs_reg *reg)
{
   return var_from_vgrf[reg->reg] + reg->reg_offset;
}

fs_live_variables::fs_live_variables(fs_visitor *v, const cfg_t *cfg)
   : v(v), cfg(cfg)
{
   mem_ctx = ralloc_context(NULL);

   num_vgrfs = v->virtual_grf_count;
   num_vars = 0;
   var_from_vgrf = rzalloc_array(mem_ctx, int, num_vgrfs);
   for (int i = 0; i < num_vgrfs; i++) {
      var_from_vgrf[i] = num_vars;
      num_vars += v->virtual_grf_sizes[i];
   }

   vgrf_from_var = rzalloc_array(mem_ctx, int, num_vars);
   for (int i = 0; i < num_vgrfs; i++) {
      for (int j = 0; j < v->virtual_grf_sizes[i]; j++) {
         vgrf_from_var[var_from_vgrf[i] + j] = i;
      }
   }

   start = ralloc_array(mem_ctx, int, num_vars);
   end = rzalloc_array(mem_ctx, int, num_vars);
   for (int i = 0; i < num_vars; i++) {
      start[i] = MAX_INSTRUCTION;
      end[i] = -1;
   }

   bd = rzalloc_array(mem_ctx, struct block_data, cfg->num_blocks);

   bitset_words = BITSET_WORDS(num_vars);
   for (int i = 0; i < cfg->num_blocks; i++) {
      bd[i].def = rzalloc_array(mem_ctx, BITSET_WORD, bitset_words);
      bd[i].use = rzalloc_array(mem_ctx, BITSET_WORD, bitset_words);
      bd[i].livein = rzalloc_array(mem_ctx, BITSET_WORD, bitset_words);
      bd[i].liveout = rzalloc_array(mem_ctx, BITSET_WORD, bitset_words);
   }

   setup_def_use();
   compute_live_variables();
   compute_start_end();
}

fs_live_variables::~fs_live_variables()
{
   ralloc_free(mem_ctx);
}

void
fs_visitor::invalidate_live_intervals()
{
   ralloc_free(live_intervals);
   live_intervals = NULL;
}

/**
 * Compute the live intervals for each virtual GRF.
 *
 * This uses the per-component use/def data, but combines it to produce
 * information about whole VGRFs.
 */
void
fs_visitor::calculate_live_intervals()
{
   if (this->live_intervals)
      return;

   int num_vgrfs = this->virtual_grf_count;
   ralloc_free(this->virtual_grf_start);
   ralloc_free(this->virtual_grf_end);
   virtual_grf_start = ralloc_array(mem_ctx, int, num_vgrfs);
   virtual_grf_end = ralloc_array(mem_ctx, int, num_vgrfs);

   for (int i = 0; i < num_vgrfs; i++) {
      virtual_grf_start[i] = MAX_INSTRUCTION;
      virtual_grf_end[i] = -1;
   }

   this->live_intervals = new(mem_ctx) fs_live_variables(this, cfg);

   /* Merge the per-component live ranges to whole VGRF live ranges. */
   for (int i = 0; i < live_intervals->num_vars; i++) {
      int vgrf = live_intervals->vgrf_from_var[i];
      virtual_grf_start[vgrf] = MIN2(virtual_grf_start[vgrf],
                                     live_intervals->start[i]);
      virtual_grf_end[vgrf] = MAX2(virtual_grf_end[vgrf],
                                   live_intervals->end[i]);
   }
}

bool
fs_live_variables::vars_interfere(int a, int b)
{
   return !(end[b] <= start[a] ||
            end[a] <= start[b]);
}

bool
fs_visitor::virtual_grf_interferes(int a, int b)
{
   return !(virtual_grf_end[a] <= virtual_grf_start[b] ||
            virtual_grf_end[b] <= virtual_grf_start[a]);
}
<commit_msg>i965/fs_live_variables: Use var_from_vgrf insead of repeating the calculation<commit_after>/*
 * Copyright © 2012 Intel Corporation
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice (including the next
 * paragraph) shall be included in all copies or substantial portions of the
 * Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 * IN THE SOFTWARE.
 *
 * Authors:
 *    Eric Anholt <eric@anholt.net>
 *
 */

#include "brw_cfg.h"
#include "brw_fs_live_variables.h"

using namespace brw;

#define MAX_INSTRUCTION (1 << 30)

/** @file brw_fs_live_variables.cpp
 *
 * Support for calculating liveness information about virtual GRFs.
 *
 * This produces a live interval for each whole virtual GRF.  We could
 * choose to expose per-component live intervals for VGRFs of size > 1,
 * but we currently do not.  It is easier for the consumers of this
 * information to work with whole VGRFs.
 *
 * However, we internally track use/def information at the per-component
 * (reg_offset) level for greater accuracy.  Large VGRFs may be accessed
 * piecemeal over many (possibly non-adjacent) instructions.  In this case,
 * examining a single instruction is insufficient to decide whether a whole
 * VGRF is ultimately used or defined.  Tracking individual components
 * allows us to easily assemble this information.
 *
 * See Muchnick's Advanced Compiler Design and Implementation, section
 * 14.1 (p444).
 */

void
fs_live_variables::setup_one_read(bblock_t *block, fs_inst *inst,
                                  int ip, fs_reg reg)
{
   int var = var_from_reg(&reg);
   assert(var < num_vars);

   /* In most cases, a register can be written over safely by the
    * same instruction that is its last use.  For a single
    * instruction, the sources are dereferenced before writing of the
    * destination starts (naturally).  This gets more complicated for
    * simd16, because the instruction:
    *
    * add(16)      g4<1>F      g4<8,8,1>F   g6<8,8,1>F
    *
    * is actually decoded in hardware as:
    *
    * add(8)       g4<1>F      g4<8,8,1>F   g6<8,8,1>F
    * add(8)       g5<1>F      g5<8,8,1>F   g7<8,8,1>F
    *
    * Which is safe.  However, if we have uniform accesses
    * happening, we get into trouble:
    *
    * add(8)       g4<1>F      g4<0,1,0>F   g6<8,8,1>F
    * add(8)       g5<1>F      g4<0,1,0>F   g7<8,8,1>F
    *
    * Now our destination for the first instruction overwrote the
    * second instruction's src0, and we get garbage for those 8
    * pixels.  There's a similar issue for the pre-gen6
    * pixel_x/pixel_y, which are registers of 16-bit values and thus
    * would get stomped by the first decode as well.
    */
   int end_ip = ip;
   if (v->dispatch_width == 16 && (reg.stride == 0 ||
                                   reg.type == BRW_REGISTER_TYPE_UW ||
                                   reg.type == BRW_REGISTER_TYPE_W ||
                                   reg.type == BRW_REGISTER_TYPE_UB ||
                                   reg.type == BRW_REGISTER_TYPE_B)) {
      end_ip++;
   }

   start[var] = MIN2(start[var], ip);
   end[var] = MAX2(end[var], end_ip);

   /* The use[] bitset marks when the block makes use of a variable (VGRF
    * channel) without having completely defined that variable within the
    * block.
    */
   if (!BITSET_TEST(bd[block->num].def, var))
      BITSET_SET(bd[block->num].use, var);
}

void
fs_live_variables::setup_one_write(bblock_t *block, fs_inst *inst,
                                   int ip, fs_reg reg)
{
   int var = var_from_reg(&reg);
   assert(var < num_vars);

   start[var] = MIN2(start[var], ip);
   end[var] = MAX2(end[var], ip);

   /* The def[] bitset marks when an initialization in a block completely
    * screens off previous updates of that variable (VGRF channel).
    */
   if (inst->dst.file == GRF && !inst->is_partial_write()) {
      if (!BITSET_TEST(bd[block->num].use, var))
         BITSET_SET(bd[block->num].def, var);
   }
}

/**
 * Sets up the use[] and def[] bitsets.
 *
 * The basic-block-level live variable analysis needs to know which
 * variables get used before they're completely defined, and which
 * variables are completely defined before they're used.
 *
 * These are tracked at the per-component level, rather than whole VGRFs.
 */
void
fs_live_variables::setup_def_use()
{
   int ip = 0;

   foreach_block (block, cfg) {
      assert(ip == block->start_ip);
      if (block->num > 0)
	 assert(cfg->blocks[block->num - 1]->end_ip == ip - 1);

      foreach_inst_in_block(fs_inst, inst, block) {
	 /* Set use[] for this instruction */
	 for (unsigned int i = 0; i < inst->sources; i++) {
            fs_reg reg = inst->src[i];

            if (reg.file != GRF)
               continue;

            for (int j = 0; j < inst->regs_read(v, i); j++) {
               setup_one_read(block, inst, ip, reg);
               reg.reg_offset++;
            }
	 }

         /* Set def[] for this instruction */
         if (inst->dst.file == GRF) {
            fs_reg reg = inst->dst;
            for (int j = 0; j < inst->regs_written; j++) {
               setup_one_write(block, inst, ip, reg);
               reg.reg_offset++;
            }
	 }

	 ip++;
      }
   }
}

/**
 * The algorithm incrementally sets bits in liveout and livein,
 * propagating it through control flow.  It will eventually terminate
 * because it only ever adds bits, and stops when no bits are added in
 * a pass.
 */
void
fs_live_variables::compute_live_variables()
{
   bool cont = true;

   while (cont) {
      cont = false;

      foreach_block (block, cfg) {
	 /* Update livein */
	 for (int i = 0; i < bitset_words; i++) {
            BITSET_WORD new_livein = (bd[block->num].use[i] |
                                      (bd[block->num].liveout[i] &
                                       ~bd[block->num].def[i]));
	    if (new_livein & ~bd[block->num].livein[i]) {
               bd[block->num].livein[i] |= new_livein;
               cont = true;
	    }
	 }

	 /* Update liveout */
	 foreach_list_typed(bblock_link, child_link, link, &block->children) {
	    bblock_t *child = child_link->block;

	    for (int i = 0; i < bitset_words; i++) {
               BITSET_WORD new_liveout = (bd[child->num].livein[i] &
                                          ~bd[block->num].liveout[i]);
               if (new_liveout) {
                  bd[block->num].liveout[i] |= new_liveout;
                  cont = true;
               }
	    }
	 }
      }
   }
}

/**
 * Extend the start/end ranges for each variable to account for the
 * new information calculated from control flow.
 */
void
fs_live_variables::compute_start_end()
{
   foreach_block (block, cfg) {
      for (int i = 0; i < num_vars; i++) {
	 if (BITSET_TEST(bd[block->num].livein, i)) {
	    start[i] = MIN2(start[i], block->start_ip);
	    end[i] = MAX2(end[i], block->start_ip);
	 }

	 if (BITSET_TEST(bd[block->num].liveout, i)) {
	    start[i] = MIN2(start[i], block->end_ip);
	    end[i] = MAX2(end[i], block->end_ip);
	 }

      }
   }
}

int
fs_live_variables::var_from_reg(fs_reg *reg)
{
   return var_from_vgrf[reg->reg] + reg->reg_offset;
}

fs_live_variables::fs_live_variables(fs_visitor *v, const cfg_t *cfg)
   : v(v), cfg(cfg)
{
   mem_ctx = ralloc_context(NULL);

   num_vgrfs = v->virtual_grf_count;
   num_vars = 0;
   var_from_vgrf = rzalloc_array(mem_ctx, int, num_vgrfs);
   for (int i = 0; i < num_vgrfs; i++) {
      var_from_vgrf[i] = num_vars;
      num_vars += v->virtual_grf_sizes[i];
   }

   vgrf_from_var = rzalloc_array(mem_ctx, int, num_vars);
   for (int i = 0; i < num_vgrfs; i++) {
      for (int j = 0; j < v->virtual_grf_sizes[i]; j++) {
         vgrf_from_var[var_from_vgrf[i] + j] = i;
      }
   }

   start = ralloc_array(mem_ctx, int, num_vars);
   end = rzalloc_array(mem_ctx, int, num_vars);
   for (int i = 0; i < num_vars; i++) {
      start[i] = MAX_INSTRUCTION;
      end[i] = -1;
   }

   bd = rzalloc_array(mem_ctx, struct block_data, cfg->num_blocks);

   bitset_words = BITSET_WORDS(num_vars);
   for (int i = 0; i < cfg->num_blocks; i++) {
      bd[i].def = rzalloc_array(mem_ctx, BITSET_WORD, bitset_words);
      bd[i].use = rzalloc_array(mem_ctx, BITSET_WORD, bitset_words);
      bd[i].livein = rzalloc_array(mem_ctx, BITSET_WORD, bitset_words);
      bd[i].liveout = rzalloc_array(mem_ctx, BITSET_WORD, bitset_words);
   }

   setup_def_use();
   compute_live_variables();
   compute_start_end();
}

fs_live_variables::~fs_live_variables()
{
   ralloc_free(mem_ctx);
}

void
fs_visitor::invalidate_live_intervals()
{
   ralloc_free(live_intervals);
   live_intervals = NULL;
}

/**
 * Compute the live intervals for each virtual GRF.
 *
 * This uses the per-component use/def data, but combines it to produce
 * information about whole VGRFs.
 */
void
fs_visitor::calculate_live_intervals()
{
   if (this->live_intervals)
      return;

   int num_vgrfs = this->virtual_grf_count;
   ralloc_free(this->virtual_grf_start);
   ralloc_free(this->virtual_grf_end);
   virtual_grf_start = ralloc_array(mem_ctx, int, num_vgrfs);
   virtual_grf_end = ralloc_array(mem_ctx, int, num_vgrfs);

   for (int i = 0; i < num_vgrfs; i++) {
      virtual_grf_start[i] = MAX_INSTRUCTION;
      virtual_grf_end[i] = -1;
   }

   this->live_intervals = new(mem_ctx) fs_live_variables(this, cfg);

   /* Merge the per-component live ranges to whole VGRF live ranges. */
   for (int i = 0; i < live_intervals->num_vars; i++) {
      int vgrf = live_intervals->vgrf_from_var[i];
      virtual_grf_start[vgrf] = MIN2(virtual_grf_start[vgrf],
                                     live_intervals->start[i]);
      virtual_grf_end[vgrf] = MAX2(virtual_grf_end[vgrf],
                                   live_intervals->end[i]);
   }
}

bool
fs_live_variables::vars_interfere(int a, int b)
{
   return !(end[b] <= start[a] ||
            end[a] <= start[b]);
}

bool
fs_visitor::virtual_grf_interferes(int a, int b)
{
   return !(virtual_grf_end[a] <= virtual_grf_start[b] ||
            virtual_grf_end[b] <= virtual_grf_start[a]);
}
<|endoftext|>


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

#include <stdexcept>

#include "stdafx.h"
#include "passthru_streambuf.h"

using namespace std;

namespace zorba {

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

passthru_streambuf::passthru_streambuf( char const*, streambuf *orig ) :
  proxy_streambuf( orig )
{
  if ( !orig )
    throw invalid_argument( "null streambuf" );
}

passthru_streambuf::~passthru_streambuf() {
  // out-of-line since it's virtual
}

void passthru_streambuf::imbue( std::locale const &loc ) {
  original()->pubimbue( loc );
}

bool passthru_streambuf::is_necessary( char const *cc_charset ) {
  if ( !*cc_charset )
    throw invalid_argument( "empty charset" );
  zstring charset( cc_charset );
  ascii::trim_whitespace( charset );
  ascii::to_upper( charset );
  return charset != "ASCII"
      && charset != "US-ASCII"
      && charset != "UTF-8";
}

bool passthru_streambuf::is_supported( char const *cc_charset ) {
  return !is_necessary( cc_charset );
}

passthru_streambuf::pos_type
passthru_streambuf::seekoff( off_type o, ios_base::seekdir d,
                             ios_base::openmode m ) {
  return original()->pubseekoff( o, d, m );
}

passthru_streambuf::pos_type
passthru_streambuf::seekpos( pos_type p, ios_base::openmode m ) {
  return original()->pubseekpos( p, m );
}

streambuf* passthru_streambuf::setbuf( char_type *p, streamsize s ) {
  original()->pubsetbuf( p, s );
  return this;
}

streamsize passthru_streambuf::showmanyc() {
  return original()->in_avail();
}

int passthru_streambuf::sync() {
  return original()->pubsync();
}

passthru_streambuf::int_type passthru_streambuf::overflow( int_type c ) {
  return original()->sputc( c );
}

passthru_streambuf::int_type passthru_streambuf::pbackfail( int_type c ) {
  return original()->sputbackc( traits_type::to_char_type( c ) );
}

passthru_streambuf::int_type passthru_streambuf::uflow() {
  return original()->sbumpc();
}

passthru_streambuf::int_type passthru_streambuf::underflow() {
  return original()->sgetc();
}

streamsize passthru_streambuf::xsgetn( char_type *to, streamsize size ) {
  return original()->sgetn( to, size );
}

streamsize passthru_streambuf::xsputn( char_type const *from,
                                       streamsize size ) {
  return original()->sputn( from, size );
}

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

} // namespace zorba
/* vim:set et sw=2 ts=2: */
<commit_msg>Better pbackfail().<commit_after>/*
 * Copyright 2006-2008 The FLWOR Foundation.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <stdexcept>

#include "stdafx.h"
#include "passthru_streambuf.h"

using namespace std;

namespace zorba {

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

passthru_streambuf::passthru_streambuf( char const*, streambuf *orig ) :
  proxy_streambuf( orig )
{
  if ( !orig )
    throw invalid_argument( "null streambuf" );
}

passthru_streambuf::~passthru_streambuf() {
  // out-of-line since it's virtual
}

void passthru_streambuf::imbue( std::locale const &loc ) {
  original()->pubimbue( loc );
}

bool passthru_streambuf::is_necessary( char const *cc_charset ) {
  if ( !*cc_charset )
    throw invalid_argument( "empty charset" );
  zstring charset( cc_charset );
  ascii::trim_whitespace( charset );
  ascii::to_upper( charset );
  return charset != "ASCII"
      && charset != "US-ASCII"
      && charset != "UTF-8";
}

bool passthru_streambuf::is_supported( char const *cc_charset ) {
  return !is_necessary( cc_charset );
}

passthru_streambuf::pos_type
passthru_streambuf::seekoff( off_type o, ios_base::seekdir d,
                             ios_base::openmode m ) {
  return original()->pubseekoff( o, d, m );
}

passthru_streambuf::pos_type
passthru_streambuf::seekpos( pos_type p, ios_base::openmode m ) {
  return original()->pubseekpos( p, m );
}

streambuf* passthru_streambuf::setbuf( char_type *p, streamsize s ) {
  original()->pubsetbuf( p, s );
  return this;
}

streamsize passthru_streambuf::showmanyc() {
  return original()->in_avail();
}

int passthru_streambuf::sync() {
  return original()->pubsync();
}

passthru_streambuf::int_type passthru_streambuf::overflow( int_type c ) {
  return original()->sputc( c );
}

passthru_streambuf::int_type passthru_streambuf::pbackfail( int_type c ) {
  return  traits_type::eq_int_type( c, traits_type::eof() ) ?
          c : proxy_buf_->sputbackc( traits_type::to_char_type( c ) );
}

passthru_streambuf::int_type passthru_streambuf::uflow() {
  return original()->sbumpc();
}

passthru_streambuf::int_type passthru_streambuf::underflow() {
  return original()->sgetc();
}

streamsize passthru_streambuf::xsgetn( char_type *to, streamsize size ) {
  return original()->sgetn( to, size );
}

streamsize passthru_streambuf::xsputn( char_type const *from,
                                       streamsize size ) {
  return original()->sputn( from, size );
}

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

} // namespace zorba
/* vim:set et sw=2 ts=2: */
<|endoftext|>


<commit_before>#include "btree/append_prepend.hpp"
#include "btree/modify_oper.hpp"
#include "buffer_cache/co_functions.hpp"

struct btree_append_prepend_oper_t : public btree_modify_oper_t {

    btree_append_prepend_oper_t(boost::shared_ptr<data_provider_t> _data, bool _append)
        : data(_data), append(_append)
    { }

    bool operate(const boost::shared_ptr<transaction_t>& txn, btree_value *old_value, boost::scoped_ptr<large_buf_t>& old_large_buflock, btree_value **new_value, boost::scoped_ptr<large_buf_t>& new_large_buflock) {
        if (!old_value) {
            result = apr_not_found;
            return false;
        }

        size_t new_size = old_value->value_size() + data->get_size();
        if (new_size > MAX_VALUE_SIZE) {
            result = apr_too_large;
            return false;
        }

        // Copy flags, exptime, etc.

        valuecpy(&value, old_value);
        if (!old_value->is_large()) {
            // HACK: we set the value.size in advance preparation when
            // the old value was not large.  If the old value _IS_
            // large, we leave it with the old size, and then we
            // adjust value.size by refsize_adjustment below.

            // The vaule_size setter only behaves correctly when we're
            // setting a new large value.
            value.value_size(new_size, slice->cache()->get_block_size());
        }

        buffer_group_t buffer_group;

        // Figure out where the data is going to need to go and prepare a place for it

        if (new_size <= MAX_IN_NODE_VALUE_SIZE) { // small -> small
            rassert(!old_value->is_large());
            // This does unnecessary copying now.
            if (append) {
                buffer_group.add_buffer(data->get_size(), value.value() + old_value->value_size());
            } else { // prepend
                memmove(value.value() + data->get_size(), value.value(), old_value->value_size());
                buffer_group.add_buffer(data->get_size(), value.value());
            }
        } else {
            // Prepare the large value if necessary.
            if (!old_value->is_large()) { // small -> large; allocate a new large value and copy existing value into it.
                large_buflock.reset(new large_buf_t(txn, value.lb_ref(), btree_value::lbref_limit, rwi_write));
                large_buflock->allocate(new_size);
                if (append) large_buflock->fill_at(0, old_value->value(), old_value->value_size());
                else        large_buflock->fill_at(data->get_size(), old_value->value(), old_value->value_size());
            } else { // large -> large; expand existing large value
                memcpy(&value, old_value, MAX_BTREE_VALUE_SIZE);
                large_buflock.swap(old_large_buflock);
                large_buflock->HACK_root_ref(value.lb_ref());
                int refsize_adjustment;

                if (append) {
                    // TIED large_buflock TO value.
                    large_buflock->append(data->get_size(), &refsize_adjustment);
                }
                else {
                    large_buflock->prepend(data->get_size(), &refsize_adjustment);
                }

                value.size += refsize_adjustment;
            }

            // Figure out the pointers and sizes where data needs to go

            uint32_t fill_size = data->get_size();
            uint32_t start_pos = append ? old_value->value_size() : 0;

            large_buflock->bufs_at(start_pos, fill_size, false, &buffer_group);
        }

        // Dispatch the data request

        data->get_data_into_buffers(&buffer_group);

        *new_value = &value;
        new_large_buflock.swap(large_buflock);

        result = apr_success;
        return true;
    }

    int compute_expected_change_count(const size_t block_size) {
        if (data->get_size() < MAX_IN_NODE_VALUE_SIZE) {
            return 1;
        } else {
            size_t size = ceil_aligned(data->get_size(), block_size);
            // one for the leaf node plus the number of blocks required to hold the large value
            return 1 + size / block_size;
        }
    }

    void actually_acquire_large_value(large_buf_t *lb) {
        if (append) {
            co_acquire_large_buf_rhs(lb);
        } else {
            co_acquire_large_buf_lhs(lb);
        }
    }

    append_prepend_result_t result;

    boost::shared_ptr<data_provider_t> data;
    bool append;   // true = append, false = prepend

    boost::scoped_ptr<large_buf_t> large_buflock;

    union {
        char value_memory[MAX_BTREE_VALUE_SIZE];
        btree_value value;
    };
};

append_prepend_result_t btree_append_prepend(const store_key_t &key, btree_slice_t *slice, boost::shared_ptr<data_provider_t> data, bool append, castime_t castime, order_token_t token) {
    btree_append_prepend_oper_t oper(data, append);
    run_btree_modify_oper(&oper, slice, key, castime, token);
    return oper.result;
}
<commit_msg>Got append_prepend.cc compiling.<commit_after>#include "btree/append_prepend.hpp"
#include "btree/modify_oper.hpp"
#include "buffer_cache/co_functions.hpp"

struct btree_append_prepend_oper_t : public btree_modify_oper_t {

    btree_append_prepend_oper_t(boost::shared_ptr<data_provider_t> _data, bool _append)
        : data(_data), append(_append)
    { }

    bool operate(const boost::shared_ptr<transaction_t>& txn, scoped_malloc<btree_value_t>& value) {
        if (!value) {
            result = apr_not_found;
            return false;
        }

        size_t new_size = value->value_size() + data->get_size();
        if (new_size > MAX_VALUE_SIZE) {
            result = apr_too_large;
            return false;
        }

        blob_t b(txn->get_cache()->get_block_size(), value->value_ref(), blob::btree_maxreflen);
        buffer_group_t buffer_group;
        blob_acq_t acqs;

        size_t old_size = b.valuesize();
        if (append) {
            b.append_region(txn.get(), data->get_size());
            b.expose_region(txn.get(), rwi_write, old_size, data->get_size(), &buffer_group, &acqs);
        } else {
            b.prepend_region(txn.get(), data->get_size());
            b.expose_region(txn.get(), rwi_write, 0, data->get_size(), &buffer_group, &acqs);
        }

        data->get_data_into_buffers(&buffer_group);
        result = apr_success;
        return true;
    }

    int compute_expected_change_count(const size_t block_size) {
        if (data->get_size() < MAX_IN_NODE_VALUE_SIZE) {
            return 1;
        } else {
            size_t size = ceil_aligned(data->get_size(), block_size);
            // one for the leaf node plus the number of blocks required to hold the large value
            return 1 + size / block_size;
        }
    }

    void actually_acquire_large_value(large_buf_t *lb) {
        if (append) {
            co_acquire_large_buf_rhs(lb);
        } else {
            co_acquire_large_buf_lhs(lb);
        }
    }

    append_prepend_result_t result;

    boost::shared_ptr<data_provider_t> data;
    bool append;   // true = append, false = prepend
};

append_prepend_result_t btree_append_prepend(const store_key_t &key, btree_slice_t *slice, boost::shared_ptr<data_provider_t> data, bool append, castime_t castime, order_token_t token) {
    btree_append_prepend_oper_t oper(data, append);
    run_btree_modify_oper(&oper, slice, key, castime, token);
    return oper.result;
}
<|endoftext|>


<commit_before>/*
 * Clever language
 * Copyright (c) 2010 Clever Team
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 *
 * $Id$
 */

#include <string>
#include "opcodes.h"

namespace clever {

/*
 * Dumps an opcode
 */
void Opcode::dump() {
	printf("%-15s | ", getOpName(m_op_type));
	printf("%-15s | ", dumpOp("op1", m_op1));
	printf("%-15s | ", dumpOp("op2", m_op1));
	printf("%-15s\n", dumpOp("result", m_result));
}

/*
 * Returns the opcode name
 */
const char* Opcode::getOpName(Opcodes op) {
#define CASE(x) case x: return #x

	switch (op) {
		CASE(OP_ECHO);
		CASE(OP_PLUS);
		CASE(OP_DIV);
		CASE(OP_MULT);
		CASE(OP_MINUS);
		CASE(OP_NEW_SCOPE);
		CASE(OP_END_SCOPE);
		CASE(OP_VAR_DECL);
		CASE(OP_BW_OR);
		CASE(OP_BW_AND);
		CASE(OP_BW_XOR);
		CASE(OP_PRE_INC);
		CASE(OP_PRE_DEC);
		CASE(OP_POS_INC);
		CASE(OP_POS_DEC);
		CASE(OP_JMPZ);
		CASE(OP_JMP);
		default:
			return "UNKNOWN";
	}
}

const char* Opcode::dumpOp(const char* label, Value* op) {
	if (op) {
		return std::string(std::string(label) + ": " + op->toString()).c_str();
	} else {
		return std::string(std::string(label) + ": UNUSED").c_str();
	}
}

} // clever<commit_msg>- Typo<commit_after>/*
 * Clever language
 * Copyright (c) 2010 Clever Team
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 *
 * $Id$
 */

#include <string>
#include "opcodes.h"

namespace clever {

/*
 * Dumps an opcode
 */
void Opcode::dump() {
	printf("%-15s | ", getOpName(m_op_type));
	printf("%-15s | ", dumpOp("op1", m_op1));
	printf("%-15s | ", dumpOp("op2", m_op2));
	printf("%-15s\n", dumpOp("result", m_result));
}

/*
 * Returns the opcode name
 */
const char* Opcode::getOpName(Opcodes op) {
#define CASE(x) case x: return #x

	switch (op) {
		CASE(OP_ECHO);
		CASE(OP_PLUS);
		CASE(OP_DIV);
		CASE(OP_MULT);
		CASE(OP_MINUS);
		CASE(OP_NEW_SCOPE);
		CASE(OP_END_SCOPE);
		CASE(OP_VAR_DECL);
		CASE(OP_BW_OR);
		CASE(OP_BW_AND);
		CASE(OP_BW_XOR);
		CASE(OP_PRE_INC);
		CASE(OP_PRE_DEC);
		CASE(OP_POS_INC);
		CASE(OP_POS_DEC);
		CASE(OP_JMPZ);
		CASE(OP_JMP);
		default:
			return "UNKNOWN";
	}
}

const char* Opcode::dumpOp(const char* label, Value* op) {
	if (op) {
		return std::string(std::string(label) + ": " + op->toString()).c_str();
	} else {
		return std::string(std::string(label) + ": UNUSED").c_str();
	}
}

} // clever<|endoftext|>


<commit_before>/**
 * Copyright : falcon build system (c) 2014.
 * LICENSE : see accompanying LICENSE file for details.
 */

#include <cassert>

#include <git2.h>
#include <git2/repository.h>

#include "cache_git_directory.h"

#include "graph.h"
#include "logging.h"

namespace falcon {

CacheGitDirectory::CacheGitDirectory(const std::string& gitRepository,
                                     CacheFS cacheFs)
    : gitRepository_(gitRepository)
    , cacheFs_(cacheFs) { }

bool CacheGitDirectory::checkIsGitRepository() const {
  git_threads_init();
  git_repository *repo = NULL;
  bool found = !git_repository_open(&repo, gitRepository_.c_str());
  git_repository_free(repo);
  git_threads_shutdown();
  return found;
}

void CacheGitDirectory::updateRef() {
  currentGitRef_ = "";
  git_repository *repo = NULL;
  git_reference *head = NULL;

  git_threads_init();
  int r = git_repository_open(&repo, gitRepository_.c_str());
  if (r != 0) {
    LOG(INFO) << "Cannot open git repository " << gitRepository_;
    goto cleanup;
  }

  if (git_repository_head_detached(repo)) {
    LOG(INFO) << "We are in detached state";
    goto cleanup;
  }

  r = git_repository_head(&head, repo);
  if (r != 0) {
    LOG(INFO) << "Cannot get current ref head";
    goto cleanup;
  }

  currentGitRef_ = git_reference_name(head);
  LOG(INFO) << "found ref: " << currentGitRef_;

cleanup:
  git_repository_free(repo);
  git_threads_shutdown();
}

bool CacheGitDirectory::isInRef() const {
  return !currentGitRef_.empty();
}

void CacheGitDirectory::registerNode(const std::string& hash, Node* node) {
  auto itRefMap = gitNodeMap_.find(node);
  if (itRefMap == gitNodeMap_.end()) {
    auto itInserted = gitNodeMap_.insert(std::make_pair(node, RefMap()));
    itRefMap = itInserted.first;
  }
  registerEntryInRefMap(hash, itRefMap->second);
}

void CacheGitDirectory::registerRule(const std::string& hash, Rule* rule) {
  auto itRefMap = gitRuleMap_.find(rule);
  if (itRefMap == gitRuleMap_.end()) {
    auto itInserted = gitRuleMap_.insert(std::make_pair(rule, RefMap()));
    itRefMap = itInserted.first;
  }
  registerEntryInRefMap(hash, itRefMap->second);
}

void CacheGitDirectory::registerEntryInRefMap(const std::string& hash,
                                              RefMap& refMap) {
  assert(isInRef());

  /* Find the cache entry that corresponds to this hash.
   * Create a new entry if not found. */
  auto itFind = gitHashMap_.find(hash);
  GitCacheEntry* entry;
  if (itFind == gitHashMap_.end()) {
    entry = new GitCacheEntry();
    entry->hash = hash;
    gitHashMap_[hash] = entry;
  } else {
    entry = itFind->second;
  }

  /* Look in the refMap for any CacheEntry that was already linked to the
   * current git ref. */
  auto itPrevEntry = refMap.find(currentGitRef_);
  if (itPrevEntry != refMap.end()) {
    GitCacheEntry* prevEntry = itPrevEntry->second;
    assert(prevEntry->numGitRefs > 0);
    prevEntry->numGitRefs--;
    if (prevEntry->numGitRefs == 0 && prevEntry != entry) {
      DLOG(INFO) << "deleting " << prevEntry->hash;
      cacheFs_.delEntry(prevEntry->hash);
      gitHashMap_.erase(prevEntry->hash);
      delete prevEntry;
    }
  }

  refMap[currentGitRef_] = entry;
  entry->numGitRefs++;
}

} // namespace falcon
<commit_msg>update libgit2 calls to match last Libgit2 API<commit_after>/**
 * Copyright : falcon build system (c) 2014.
 * LICENSE : see accompanying LICENSE file for details.
 */

#include <cassert>

#include <git2.h>
#include <git2/repository.h>

#include "cache_git_directory.h"

#include "graph.h"
#include "logging.h"

namespace falcon {

CacheGitDirectory::CacheGitDirectory(const std::string& gitRepository,
                                     CacheFS cacheFs)
    : gitRepository_(gitRepository)
    , cacheFs_(cacheFs) { }

bool CacheGitDirectory::checkIsGitRepository() const {
  git_libgit2_init();
  git_repository *repo = NULL;
  bool found = !git_repository_open(&repo, gitRepository_.c_str());
  git_repository_free(repo);
  git_libgit2_shutdown();
  return found;
}

void CacheGitDirectory::updateRef() {
  currentGitRef_ = "";
  git_repository *repo = NULL;
  git_reference *head = NULL;

  git_libgit2_init();
  int r = git_repository_open(&repo, gitRepository_.c_str());
  if (r != 0) {
    LOG(INFO) << "Cannot open git repository " << gitRepository_;
    goto cleanup;
  }

  if (git_repository_head_detached(repo)) {
    LOG(INFO) << "We are in detached state";
    goto cleanup;
  }

  r = git_repository_head(&head, repo);
  if (r != 0) {
    LOG(INFO) << "Cannot get current ref head";
    goto cleanup;
  }

  currentGitRef_ = git_reference_name(head);
  LOG(INFO) << "found ref: " << currentGitRef_;

cleanup:
  git_repository_free(repo);
  git_libgit2_shutdown();
}

bool CacheGitDirectory::isInRef() const {
  return !currentGitRef_.empty();
}

void CacheGitDirectory::registerNode(const std::string& hash, Node* node) {
  auto itRefMap = gitNodeMap_.find(node);
  if (itRefMap == gitNodeMap_.end()) {
    auto itInserted = gitNodeMap_.insert(std::make_pair(node, RefMap()));
    itRefMap = itInserted.first;
  }
  registerEntryInRefMap(hash, itRefMap->second);
}

void CacheGitDirectory::registerRule(const std::string& hash, Rule* rule) {
  auto itRefMap = gitRuleMap_.find(rule);
  if (itRefMap == gitRuleMap_.end()) {
    auto itInserted = gitRuleMap_.insert(std::make_pair(rule, RefMap()));
    itRefMap = itInserted.first;
  }
  registerEntryInRefMap(hash, itRefMap->second);
}

void CacheGitDirectory::registerEntryInRefMap(const std::string& hash,
                                              RefMap& refMap) {
  assert(isInRef());

  /* Find the cache entry that corresponds to this hash.
   * Create a new entry if not found. */
  auto itFind = gitHashMap_.find(hash);
  GitCacheEntry* entry;
  if (itFind == gitHashMap_.end()) {
    entry = new GitCacheEntry();
    entry->hash = hash;
    gitHashMap_[hash] = entry;
  } else {
    entry = itFind->second;
  }

  /* Look in the refMap for any CacheEntry that was already linked to the
   * current git ref. */
  auto itPrevEntry = refMap.find(currentGitRef_);
  if (itPrevEntry != refMap.end()) {
    GitCacheEntry* prevEntry = itPrevEntry->second;
    assert(prevEntry->numGitRefs > 0);
    prevEntry->numGitRefs--;
    if (prevEntry->numGitRefs == 0 && prevEntry != entry) {
      DLOG(INFO) << "deleting " << prevEntry->hash;
      cacheFs_.delEntry(prevEntry->hash);
      gitHashMap_.erase(prevEntry->hash);
      delete prevEntry;
    }
  }

  refMap[currentGitRef_] = entry;
  entry->numGitRefs++;
}

} // namespace falcon
<|endoftext|>


<commit_before>/**
 * 	Result.cpp
 *
 * 	Class representing a MySQL result set
 *
 * 	@copyright 2014 Copernica BV
 */

/**
 *  Dependencies
 */
#include "result.h"
#include <iostream>

/**
 *	Set up namespace
 */
namespace ReactPhp {

/**
 *  Retrieve row at given offset
 */
void Result::fetchRow(Php::Parameters &params)
{
	// retrieve the parameter
	int index = params[0];

	// check for valid input
	if(index > (int)_result.size() || index < 0) throw Php::Exception("Invalid result object");

	for (auto field : _result[index])
	{
		// print the rows to the screen
		std::cout << field.first << " => " << field.second << std::endl;
	}
}

/**
 *  Is this a valid result?
 */
Php::Value Result::valid()
{
	_result.valid();

	return true;
}

/**
 *  The number of rows affected
 */
size_t Result::affectedRows()
{
	return (int)_result.affectedRows();
}

/**
 *  Get the number of rows in this result
 */
Php::Value Result::size()
{
	return (int)_result.size();
}

/**
 *  Retrieve iterator for first row
 */
Php::Value Result::begin()
{
	_result.begin();

	return true;
}

/**
 *  Retrieve iterator past the end
 */
Php::Value Result::end()
{
	_result.end();

	return true;
}

/**
 * 	End namespace
 */
}
<commit_msg>Class representing a MySQL result set<commit_after>/**
 * 	Result.cpp
 *
 * 	Class representing a MySQL result set
 *
 * 	@copyright 2014 Copernica BV
 */

/**
 *  Dependencies
 */
#include "result.h"
#include <iostream>

/**
 *  Set up namespace
 */
namespace ReactPhp {

/**
 *  Retrieve row at given offset
 */
void Result::fetchRow(Php::Parameters &params)
{
	// retrieve the parameter
	int index = params[0];

	// check for valid input
	if(index > (int)_result.size() || index < 0) throw Php::Exception("Invalid result object");

	for (auto field : _result[index])
	{
		// print the rows to the screen
		std::cout << field.first << " => " << field.second << std::endl;
	}
}

/**
 *  Is this a valid result?
 */
Php::Value Result::valid()
{
	_result.valid();

	return true;
}

/**
 *  The number of rows affected
 */
size_t Result::affectedRows()
{
	return (int)_result.affectedRows();
}

/**
 *  Get the number of rows in this result
 */
Php::Value Result::size()
{
	return (int)_result.size();
}

/**
 *  Retrieve iterator for first row
 */
Php::Value Result::begin()
{
	_result.begin();

	return true;
}

/**
 *  Retrieve iterator past the end
 */
Php::Value Result::end()
{
	_result.end();

	return true;
}

/**
 *   End of namespace
 */
}
<|endoftext|>


<commit_before>/******************************************************************************\

          This file is part of the C! library.  A.K.A the cbang library.

              Copyright (c) 2003-2017, Cauldron Development LLC
                 Copyright (c) 2003-2017, Stanford University
                             All rights reserved.

        The C! library is free software: you can redistribute it and/or
        modify it under the terms of the GNU Lesser General Public License
        as published by the Free Software Foundation, either version 2.1 of
        the License, or (at your option) any later version.

        The C! 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 the C! library.  If not, see
        <http://www.gnu.org/licenses/>.

        In addition, BSD licensing may be granted on a case by case basis
        by written permission from at least one of the copyright holders.
        You may request written permission by emailing the authors.

                For information regarding this software email:
                               Joseph Coffland
                        joseph@cauldrondevelopment.com

\******************************************************************************/

#include "TarHeader.h"

#include <cbang/Exception.h>

#include <stdio.h>
#include <errno.h>
#include <time.h>
#include <string.h>
#include <inttypes.h>

#ifndef PRIo32
#define PRIo32 "o"
#endif

#ifndef PRIo64
#if defined(_M_X64) || (defined(__x86_64__) && !defined(__ILP32__)) ||  \
  defined(__aarch64__)
#define PRIo64 "lo"
#else
#define PRIo64 "llo"
#endif
#endif

using namespace std;
using namespace cb;

#ifdef __APPLE__
static size_t __strnlen(const char *s, size_t limit) {
  size_t len = 0;
  while (len < limit && *s++) len++;
  return len;
}
#define strnlen __strnlen
#endif

TarHeader::TarHeader(const string &filename, uint64_t size) {
  setFilename(filename);
  setMode(0644);
  setOwner(0);
  setGroup(0);
  setSize(size);
  setModTime(time(0));
  setType(NORMAL_FILE);
  setLinkName("");
  memset(reserved, 0, 255);
}

void TarHeader::setFilename(const string &filename) {
  checksum_valid = false;
  writeString(filename, this->filename, 100);
}

void TarHeader::setMode(uint32_t mode) {
  checksum_valid = false;
  writeNumber(mode, this->mode, 8);
}

void TarHeader::setOwner(uint32_t owner) {
  checksum_valid = false;
  writeNumber(owner, this->owner, 8);
}

void TarHeader::setGroup(uint32_t group) {
  checksum_valid = false;
  writeNumber(group, this->group, 8);
}

void TarHeader::setSize(uint64_t size) {
  checksum_valid = false;
  writeNumber(size, this->size, 12);
}

void TarHeader::setModTime(uint64_t mod_time) {
  checksum_valid = false;
  writeNumber(mod_time, this->mod_time, 12);
}

void TarHeader::setType(type_t type) {
  checksum_valid = false;
  this->type[0] = (type & 7) + '0';
}

void TarHeader::setLinkName(const string &link_name) {
  checksum_valid = false;
  writeString(link_name, this->link_name, 100);
}

const string TarHeader::getFilename() const {
  return string(filename, strnlen(filename, 100));
}

uint32_t TarHeader::getMode() const {
  return readNumber(mode, 8);
}

uint32_t TarHeader::getOwner() const {
  return readNumber(owner, 8);
}

uint32_t TarHeader::getGroup() const {
  return readNumber(group, 8);
}

uint64_t TarHeader::getSize() const {
  return readNumber(size, 12);
}

uint64_t TarHeader::getModTime() const {
  return readNumber(mod_time, 12);
}

TarHeader::type_t TarHeader::getType() const {
  return (type_t)(type[0] - '0');
}

const string TarHeader::getLinkName() const {
  return string(link_name, strnlen(link_name, 100));
}

unsigned TarHeader::computeChecksum() {
  unsigned sum = 8 * 32;
  const char *ptr = filename;

  for (int i = 0; i < 148; i++)
    sum += *ptr++;

  ptr = type;
  for (int i = 156; i < 512; i++)
    sum += *ptr++;

  return sum;
}

unsigned TarHeader::updateChecksum() {
  unsigned sum = computeChecksum();
  writeNumber(sum, checksum, 7);
  checksum[7] = ' ';

  checksum_valid = true;

  return sum;
}

bool TarHeader::read(istream &stream) {
  stream.read(filename, 512);
  if (stream.gcount() != 512) return false;

  unsigned sum = readNumber(checksum, 6);
  if (sum != 0) {
    unsigned calculated = computeChecksum();
    if (sum != calculated)
      THROWS("Invalid checksum in tar header calculated=" << calculated
             << " expected=" << sum);
  }

  return true;
}

void TarHeader::write(ostream &stream) {
  if (!checksum_valid) updateChecksum();

  stream.write(filename, 512);
}

void TarHeader::writeNumber(uint32_t n, char *buf, unsigned length) {
  sprintf(buf, "%0*" PRIo32, length - 1, n);
}

void TarHeader::writeNumber(uint64_t n, char *buf, unsigned length) {
  sprintf(buf, "%0*" PRIo64, length - 1, n);
}

bool TarHeader::isEOF() const {
  return readNumber(checksum, 6) == 0;
}

void TarHeader::writeString(const string &s, char *buf, unsigned length) {
  strncpy(buf, s.c_str(), length);
  for (unsigned i = s.length(); i < length; i++)
    buf[i] = 0;
}

uint64_t TarHeader::readNumber(const char *buf, unsigned length) {
  uint64_t value = 0;

  for (unsigned i = 0; i < length; i++) {
    if ('0' <= buf[i] && buf[i] <= '7')
      value = (value << 3) | (buf[i] - '0');
    else if (buf[i] == ' ' || buf[i] == 0) break;
    else THROWS("Error converting number '" << string(buf, length) << "'");
  }

  return value;
}
<commit_msg>Include PPC in missing PRIo64 def<commit_after>/******************************************************************************\

          This file is part of the C! library.  A.K.A the cbang library.

              Copyright (c) 2003-2017, Cauldron Development LLC
                 Copyright (c) 2003-2017, Stanford University
                             All rights reserved.

        The C! library is free software: you can redistribute it and/or
        modify it under the terms of the GNU Lesser General Public License
        as published by the Free Software Foundation, either version 2.1 of
        the License, or (at your option) any later version.

        The C! 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 the C! library.  If not, see
        <http://www.gnu.org/licenses/>.

        In addition, BSD licensing may be granted on a case by case basis
        by written permission from at least one of the copyright holders.
        You may request written permission by emailing the authors.

                For information regarding this software email:
                               Joseph Coffland
                        joseph@cauldrondevelopment.com

\******************************************************************************/

#include "TarHeader.h"

#include <cbang/Exception.h>

#include <stdio.h>
#include <errno.h>
#include <time.h>
#include <string.h>
#include <inttypes.h>

#ifndef PRIo32
#define PRIo32 "o"
#endif

#ifndef PRIo64
#if defined(_M_X64) || (defined(__x86_64__) && !defined(__ILP32__)) ||  \
  defined(__aarch64__) || defined(__ppc64__) || defined(__PPC64__)
#define PRIo64 "lo"
#else
#define PRIo64 "llo"
#endif
#endif

using namespace std;
using namespace cb;

#ifdef __APPLE__
static size_t __strnlen(const char *s, size_t limit) {
  size_t len = 0;
  while (len < limit && *s++) len++;
  return len;
}
#define strnlen __strnlen
#endif

TarHeader::TarHeader(const string &filename, uint64_t size) {
  setFilename(filename);
  setMode(0644);
  setOwner(0);
  setGroup(0);
  setSize(size);
  setModTime(time(0));
  setType(NORMAL_FILE);
  setLinkName("");
  memset(reserved, 0, 255);
}

void TarHeader::setFilename(const string &filename) {
  checksum_valid = false;
  writeString(filename, this->filename, 100);
}

void TarHeader::setMode(uint32_t mode) {
  checksum_valid = false;
  writeNumber(mode, this->mode, 8);
}

void TarHeader::setOwner(uint32_t owner) {
  checksum_valid = false;
  writeNumber(owner, this->owner, 8);
}

void TarHeader::setGroup(uint32_t group) {
  checksum_valid = false;
  writeNumber(group, this->group, 8);
}

void TarHeader::setSize(uint64_t size) {
  checksum_valid = false;
  writeNumber(size, this->size, 12);
}

void TarHeader::setModTime(uint64_t mod_time) {
  checksum_valid = false;
  writeNumber(mod_time, this->mod_time, 12);
}

void TarHeader::setType(type_t type) {
  checksum_valid = false;
  this->type[0] = (type & 7) + '0';
}

void TarHeader::setLinkName(const string &link_name) {
  checksum_valid = false;
  writeString(link_name, this->link_name, 100);
}

const string TarHeader::getFilename() const {
  return string(filename, strnlen(filename, 100));
}

uint32_t TarHeader::getMode() const {
  return readNumber(mode, 8);
}

uint32_t TarHeader::getOwner() const {
  return readNumber(owner, 8);
}

uint32_t TarHeader::getGroup() const {
  return readNumber(group, 8);
}

uint64_t TarHeader::getSize() const {
  return readNumber(size, 12);
}

uint64_t TarHeader::getModTime() const {
  return readNumber(mod_time, 12);
}

TarHeader::type_t TarHeader::getType() const {
  return (type_t)(type[0] - '0');
}

const string TarHeader::getLinkName() const {
  return string(link_name, strnlen(link_name, 100));
}

unsigned TarHeader::computeChecksum() {
  unsigned sum = 8 * 32;
  const char *ptr = filename;

  for (int i = 0; i < 148; i++)
    sum += *ptr++;

  ptr = type;
  for (int i = 156; i < 512; i++)
    sum += *ptr++;

  return sum;
}

unsigned TarHeader::updateChecksum() {
  unsigned sum = computeChecksum();
  writeNumber(sum, checksum, 7);
  checksum[7] = ' ';

  checksum_valid = true;

  return sum;
}

bool TarHeader::read(istream &stream) {
  stream.read(filename, 512);
  if (stream.gcount() != 512) return false;

  unsigned sum = readNumber(checksum, 6);
  if (sum != 0) {
    unsigned calculated = computeChecksum();
    if (sum != calculated)
      THROWS("Invalid checksum in tar header calculated=" << calculated
             << " expected=" << sum);
  }

  return true;
}

void TarHeader::write(ostream &stream) {
  if (!checksum_valid) updateChecksum();

  stream.write(filename, 512);
}

void TarHeader::writeNumber(uint32_t n, char *buf, unsigned length) {
  sprintf(buf, "%0*" PRIo32, length - 1, n);
}

void TarHeader::writeNumber(uint64_t n, char *buf, unsigned length) {
  sprintf(buf, "%0*" PRIo64, length - 1, n);
}

bool TarHeader::isEOF() const {
  return readNumber(checksum, 6) == 0;
}

void TarHeader::writeString(const string &s, char *buf, unsigned length) {
  strncpy(buf, s.c_str(), length);
  for (unsigned i = s.length(); i < length; i++)
    buf[i] = 0;
}

uint64_t TarHeader::readNumber(const char *buf, unsigned length) {
  uint64_t value = 0;

  for (unsigned i = 0; i < length; i++) {
    if ('0' <= buf[i] && buf[i] <= '7')
      value = (value << 3) | (buf[i] - '0');
    else if (buf[i] == ' ' || buf[i] == 0) break;
    else THROWS("Error converting number '" << string(buf, length) << "'");
  }

  return value;
}
<|endoftext|>