Commit d206f67b authored by Pierre NARVOR's avatar Pierre NARVOR
Browse files

[types/BuildTarget] Simplified BuildTarget (interface now uses regular...

[types/BuildTarget] Simplified BuildTarget (interface now uses regular shared_ptr and version managed internally)
parent 7b3c7c71
......@@ -2,9 +2,10 @@
#define _DEF_RTAC_BASE_TYPES_BUILD_TARGET_H_
#include <iostream>
#include <memory>
#include <vector>
#include <rtac_base/types/Handle.h>
namespace rtac { namespace types {
// This files defines some generic types which aims at representing a very
......@@ -29,69 +30,38 @@ namespace rtac { namespace types {
// trigger the build of the targets which depends on the first. Note that this
// behavior should be transparent for the child targets.
template <typename TargetT,
template <typename T> class PointerT = std::shared_ptr>
class BuildTarget;
class BuildTargetHandle
{
public:
using TargetType = TargetT;
using Ptr = PointerT<TargetT>;
// defining a hash function to be able to use this pointer as a key in a
// std::unordered_map
struct Hash {
std::size_t operator()(const BuildTargetHandle<TargetT, PointerT>& ptr) const {
return std::hash<const TargetT*>{}(ptr.get());
}
};
using TargetPtr = Handle<const BuildTarget>;
protected:
Ptr target_;
TargetPtr target_;
unsigned int version_;
public:
BuildTargetHandle(TargetT* target = nullptr, unsigned int version = 0);
BuildTargetHandle(const Ptr& target, unsigned int version = 0);
unsigned int version() const;
bool has_changed() const; // this checks version_ vs target_->version()
void acknowledge(); // set this version_ to target_->version()
// This enables cast to point to base classes (as smart pointers would do).
template <typename OtherTargetT>
operator BuildTargetHandle<OtherTargetT, PointerT>() const;
BuildTargetHandle(const TargetPtr& target = nullptr);
// Minimal pointer behavior
TargetT& operator*();
const TargetT& operator*() const;
TargetT* get();
const TargetT* get() const;
Ptr ptr() { return target_; }
Ptr ptr() const { return target_; }
TargetT* operator->();
const TargetT* operator->() const;
bool has_changed() const; // this checks version_ vs target_->version()
void acknowledge(); // set this version_ to target_->version()
template <typename OtherTargetT>
bool operator==(const OtherTargetT* other) const;
template <typename OtherTargetT>
bool operator==(const BuildTargetHandle<OtherTargetT>& other) const;
operator bool() const;
unsigned int version() const;
TargetPtr target() const;
};
class BuildTarget
{
public:
using Ptr = BuildTargetHandle<BuildTarget>;
using ConstPtr = BuildTargetHandle<const BuildTarget>;
using Dependencies = std::vector<ConstPtr>;
using Ptr = Handle<BuildTarget>;
using ConstPtr = Handle<const BuildTarget>;
using Dependencies = std::vector<BuildTargetHandle>;
struct CircularDependencyError : std::runtime_error {
CircularDependencyError() : std::runtime_error(
"Adding the dependency would create an infinite loop") {}
......@@ -105,11 +75,6 @@ class BuildTarget
mutable bool needsBuild_;
mutable unsigned int version_;
mutable Dependencies dependencies_;
// A const version of bump version allows for this object to request a need
// build from other const methods. (For example if a dependency was
// changed).
void bump_version(bool needsRebuild = true) const;
// to_build and clean methods are to be reimplemented in subclasses.
virtual void do_build() const = 0;
......@@ -120,117 +85,19 @@ class BuildTarget
bool needs_build() const;
unsigned int version() const;
void bump_version(bool needsRebuild = true);
// A const version of bump version allows for this object to request a need
// build from other const methods. (For example if a dependency was
// changed).
void bump_version(bool needsRebuild = true) const;
void add_dependency(const ConstPtr& dep);
const Dependencies& dependencies() const;
void check_circular_dependencies(const ConstPtr& dep) const;
bool depends_on(const BuildTarget* other) const;
virtual void build() const;
virtual void clean() const {} // no cleanup by default;
};
// BuildTargetHandle implementation ////////////////////////////////////////
template <typename TargetT, template <typename T> class PointerT>
BuildTargetHandle<TargetT,PointerT>::BuildTargetHandle(TargetT* target,
unsigned int version) :
target_(target),
version_(version)
{}
template <typename TargetT, template <typename T> class PointerT>
BuildTargetHandle<TargetT,PointerT>::BuildTargetHandle(const Ptr& target,
unsigned int version) :
target_(target),
version_(version)
{}
template <typename TargetT, template <typename T> class PointerT>
unsigned int BuildTargetHandle<TargetT,PointerT>::version() const
{
return version_;
}
template <typename TargetT, template <typename T> class PointerT>
bool BuildTargetHandle<TargetT,PointerT>::has_changed() const
{
if(version_ != target_->version() || target_->needs_build())
return true;
return false;
}
template <typename TargetT, template <typename T> class PointerT>
void BuildTargetHandle<TargetT,PointerT>::acknowledge()
{
version_ = target_->version();
}
template <typename TargetT, template <typename T> class PointerT>
template <typename OtherTargetT> BuildTargetHandle<TargetT,PointerT>::operator
BuildTargetHandle<OtherTargetT, PointerT>() const
{
return BuildTargetHandle<OtherTargetT, PointerT>(target_, version_);
}
template <typename TargetT, template <typename T> class PointerT>
TargetT& BuildTargetHandle<TargetT,PointerT>::operator*()
{
return *target_;
}
template <typename TargetT, template <typename T> class PointerT>
const TargetT& BuildTargetHandle<TargetT,PointerT>::operator*() const
{
return *target_;
}
template <typename TargetT, template <typename T> class PointerT>
TargetT* BuildTargetHandle<TargetT,PointerT>::get()
{
return target_.get();
}
template <typename TargetT, template <typename T> class PointerT>
const TargetT* BuildTargetHandle<TargetT,PointerT>::get() const
{
return target_.get();
}
template <typename TargetT, template <typename T> class PointerT>
TargetT* BuildTargetHandle<TargetT,PointerT>::operator->()
{
return this->get();
}
template <typename TargetT, template <typename T> class PointerT>
const TargetT* BuildTargetHandle<TargetT,PointerT>::operator->() const
{
return this->get();
}
template <typename TargetT, template <typename T> class PointerT>
template <typename OtherTargetT>
bool BuildTargetHandle<TargetT,PointerT>::operator==(const OtherTargetT* other) const
{
return ((const void*)this->get()) == ((const void*)other);
}
template <typename TargetT, template <typename T> class PointerT>
template <typename OtherTargetT>
bool BuildTargetHandle<TargetT,PointerT>::operator==(
const BuildTargetHandle<OtherTargetT>& other) const
{
return ((const void*)this->get()) == ((const void*)other.get());
}
template <typename TargetT, template <typename T> class PointerT>
BuildTargetHandle<TargetT,PointerT>::operator bool() const
{
return !(!(target_));
}
// BuildTarget implementation ////////////////////////////////////////
}; //namespace types
}; //namespace rtac
......
......@@ -2,7 +2,35 @@
namespace rtac { namespace types {
// BuildTargetHandle implementation ////////////////////////////////////////
BuildTargetHandle::BuildTargetHandle(const TargetPtr& target) :
target_(target),
version_(target_->version())
{}
bool BuildTargetHandle::has_changed() const
{
if(version_ != target_->version() || target_->needs_build())
return true;
return false;
}
void BuildTargetHandle::acknowledge()
{
version_ = target_->version();
}
unsigned int BuildTargetHandle::version() const
{
return version_;
}
BuildTargetHandle::TargetPtr BuildTargetHandle::target() const
{
return target_;
}
// BuildTarget implementation ////////////////////////////////////////
BuildTarget::BuildTarget(const Dependencies& deps) :
needsBuild_(true),
version_(0),
......@@ -14,17 +42,15 @@ bool BuildTarget::needs_build() const
if(needsBuild_)
return true;
for(auto& dep : dependencies_) {
if(!dep) {
std::cout << "Dep is null !" << std::endl << std::flush;
if(!dep.target()) {
std::cerr << "Dep is null !" << std::endl << std::flush;
}
if(dep.has_changed()) {
this->bump_version(true);
return true;
//dep.acknowledge(); // Keeping track of changes
}
}
return false;
//return needsBuild_;
}
unsigned int BuildTarget::version() const
......@@ -38,16 +64,13 @@ void BuildTarget::bump_version(bool needsRebuild) const
version_++;
}
void BuildTarget::bump_version(bool needsRebuild)
{
if(needsRebuild) needsBuild_ = true;
version_++;
}
void BuildTarget::add_dependency(const ConstPtr& dep)
{
this->check_circular_dependencies(dep);
this->dependencies_.push_back(dep);
//this->check_circular_dependencies(dep);
if(dep->depends_on(this)) {
throw CircularDependencyError();
}
this->dependencies_.push_back(BuildTargetHandle(dep));
}
const BuildTarget::Dependencies& BuildTarget::dependencies() const
......@@ -55,16 +78,17 @@ const BuildTarget::Dependencies& BuildTarget::dependencies() const
return dependencies_;
}
void BuildTarget::check_circular_dependencies(const ConstPtr& dep) const
bool BuildTarget::depends_on(const BuildTarget* other) const
{
if(dep == this) {
throw CircularDependencyError();
if(other == this) {
return true;
}
for(auto& dep : dependencies_) {
if(dep == this) {
throw CircularDependencyError();
if(dep.target()->depends_on(other)) {
return true;
}
}
return false;
}
void BuildTarget::build() const
......@@ -72,13 +96,13 @@ void BuildTarget::build() const
if(!this->needs_build())
return;
// cleanup before build this can be a no-op
// cleanup before build. This can be a no-op
this->clean();
// Building dependencies (this will build all the dependency tree).
for(auto& dep : dependencies_) {
if(dep->needs_build()) {
dep->build();
if(dep.target()->needs_build()) {
dep.target()->build();
}
dep.acknowledge();
}
......
......@@ -8,8 +8,8 @@ class TargetBase : public BuildTarget
{
public:
using Ptr = BuildTargetHandle<TargetBase>;
using ConsPtr = BuildTargetHandle<const TargetBase>;
using Ptr = Handle<TargetBase>;
using ConsPtr = Handle<const TargetBase>;
public:
......@@ -32,8 +32,8 @@ class TargetBase : public BuildTarget
if(dependencies_.size() > 0) {
cout << "Check dependencies status:\n";
for(auto dep : dependencies_) {
cout << "dependency " << dynamic_cast<const TargetBase*>(dep.get())->id_
<< ", needs_build : " << dep->needs_build()
cout << "dependency " << dynamic_cast<const TargetBase*>(dep.target().get())->id_
<< ", needs_build : " << dep.target()->needs_build()
<< ", has_changed : " << dep.has_changed() << endl;
}
}
......@@ -49,8 +49,8 @@ class TargetChild0 : public TargetBase
{
public:
using Ptr = BuildTargetHandle<TargetChild0>;
using ConsPtr = BuildTargetHandle<const TargetChild0>;
using Ptr = Handle<TargetChild0>;
using ConsPtr = Handle<const TargetChild0>;
virtual void do_build() const {
cout << "Building TargetChild0 : " << id_ << endl;
......@@ -89,7 +89,7 @@ int main()
cout << "targetPtr2 : " << targetPtr2.get() << endl;
for(auto dep : target2->dependencies()) {
cout << "dep : " << dep.get() << endl;
cout << "dep : " << dep.target().get() << endl;
}
cout << endl;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment