Commit b8593101 authored by Damien Leroux's avatar Damien Leroux
Browse files

work in progress.

parent b4bd2f58
#ifndef _MCQTL_CACHE_H_
#define _MCQTL_CACHE_H_
/*#include "cache/call_tuple.h"*/
namespace cache {
template <typename V> struct value;
template <typename V> struct range;
template <typename V> struct collection;
template <typename C, typename T, typename... D> struct computed_value;
template <typename V> struct computed_collection;
}
#include "cache/md5.h"
#include "cache/tuple_utils.h"
#include "cache/value.h"
#include "cache/cartesian_product.h"
#include "cache/file.h"
#include "cache/factory.h"
#endif
......@@ -22,10 +22,27 @@ msg_handler_t::lock_type msg_handler_t::mutex;
namespace cache {
namespace predicate {
template <typename T> struct is_composite
: std::integral_constant<bool, T::composite> {};
#if 0
template <typename T> struct is_composite;
template <typename T> struct is_composite<value<T>> { static const bool value = false; };
template <typename T> struct is_composite<range<T>> { static const bool value = true; };
template <typename T> struct is_composite<collection<T>> { static const bool value = true; };
template <typename T> struct is_composite<value<T>>
: std::integral_constant<bool, false> {};
template <typename T> struct is_composite<range<T>>
: std::integral_constant<bool, true> {};
template <typename T> struct is_composite<collection<T>>
: std::integral_constant<bool, true> {};
template <typename X, typename T>
struct derived_from
: std::integral_constant<bool, std::is_same<X, T>::value
|| std::is_base_of<T, X>::value> {};
template <typename V, template <typename X> class T>
struct is_composite<T<V>>
: std::integral_constant<bool, derived_from<T<V>, range<V>>::value
|| derived_from<T<V>, collection<V>>::value> {};
#endif
}
}
......@@ -45,18 +62,50 @@ namespace detail {
namespace cache {
struct launch {
static std::launch& policy()
{
/*static std::launch _ = std::launch::async | std::launch::deferred;*/
static std::launch _ = std::launch::deferred;
return _;
}
};
template <bool _MultiThread>
struct launch_impl;
template <>
struct launch_impl<true> {
static std::launch& policy()
{
/*static std::launch _ = std::launch::async | std::launch::deferred;*/
static std::launch _ = std::launch::deferred;
return _;
}
template <typename Type>
using computed_type = std::future<Type>;
template <typename Type, typename FSig>
static computed_type<Type> run(FSig f)
{
return std::async(policy(), f);
}
template <typename Type>
static Type access(computed_type<Type>& ct) { return ct.get(); }
};
template <>
struct launch_impl<false> {
template <typename Type>
using computed_type = Type;
template <typename Type, typename FSig>
static computed_type<Type> run(FSig f)
{
return f();
}
template <typename Type>
static Type access(computed_type<Type>& ct) { return ct; }
};
typedef launch_impl<false> launch;
template <typename Type>
using computed_type = std::future<Type>;
/*using computed_type = Type;*/
using computed_type = launch::computed_type<Type>;
template <typename Class, typename Type, typename... Dependencies>
......@@ -67,15 +116,15 @@ struct async_computed_value : value<computed_type<Type>> {
async_computed_value(const std::tuple<Dependencies...>& dep)
: dependencies(dep)
{ val = async_compute_cache(); }
async_computed_value(std::tuple<Dependencies...>&& dep)
: dependencies(std::move(dep))
{ val = async_compute_cache(); }
/*async_computed_value(std::tuple<Dependencies...>&& dep)*/
/*: dependencies(std::move(dep))*/
/*{ val = async_compute_cache(); }*/
async_computed_value(const Dependencies&... dep)
: dependencies(dep...)
{ val = async_compute_cache(); }
async_computed_value(Dependencies&&... dep)
: dependencies(std::move(dep)...)
{ val = async_compute_cache(); }
/*async_computed_value(Dependencies&&... dep)*/
/*: dependencies(std::move(dep)...)*/
/*{ val = async_compute_cache(); }*/
async_computed_value(const async_computed_value<Class, Type, Dependencies...>&) = delete;
async_computed_value(async_computed_value<Class, Type, Dependencies...>&&) = delete;
......@@ -101,9 +150,11 @@ struct async_computed_value : value<computed_type<Type>> {
return f.str();
}
operator Type () { return val.get(); }
operator Type () { return launch::access(val); }
/*operator Type () { return val; }*/
Type v() { return launch::access(val); }
static std::string& cache_directory() { static std::string _ = DEFAULT_CACHE_DIR; return _; }
std::tuple<Dependencies...> dependencies;
......@@ -136,11 +187,10 @@ private:
computed_type<Type> async_compute_cache()
{
return std::async(std::launch::async,
[this] ()
{
return compute_cache();
});
return launch::run<Type>([this] ()
{
return compute_cache();
});
}
bool load(const std::string& filename, Type& v)
......@@ -183,13 +233,19 @@ private:
Type compute_(const Dependencies&... t)
{
return dynamic_cast<Class*>(this)->do_compute(t...);
Class* tmp = reinterpret_cast<Class*>(this);
DEBUG(__FILE__ << ':' << __LINE__ << " compute_@" << tmp << " from @" << this);
return tmp->do_compute(t...);
}
template <int... Indices>
Type compute_(sequence<Indices...>, const std::tuple<Dependencies...>& t)
{
return dynamic_cast<Class*>(this)->do_compute(std::get<Indices>(t)...);
Class* tmp = reinterpret_cast<Class*>(this);
DEBUG("type of *this = " << typeid(*this).name());
DEBUG("type of Class = " << typeid(Class).name());
DEBUG(__FILE__ << ':' << __LINE__ << " compute_@" << tmp << " from @" << this);
return tmp->do_compute(std::get<Indices>(t)...);
}
template <int I, int N> struct tuple_digest_ {
......@@ -281,10 +337,37 @@ struct computed_value : value<Type> {
: value<Type>(), task(cv.task)
{}
computed_value() : value<Type>(), task() {}
void __init(const std::tuple<Dependencies...>& d)
{
task = new task_type(d);
}
Class& operator = (const Class& c)
{
if (task) {
delete task;
}
task = c.task;
return *static_cast<Class*>(this);
}
Class& operator = (Class&& c)
{
if (task) {
delete task;
}
task = std::move(c.task);
return *static_cast<Class*>(this);
}
operator Type ()
{
return *task;
}
static const bool composite = false;
};
......@@ -330,6 +413,7 @@ struct make_task_helper<true, TASK_CLASS, Elems...> {
cartesian_product<Elems...> cp(t);
do {
/*ret.emplace_back(TASK_CLASS::get(*cp));*/
DEBUG("make_task " << (*cp));
ret.emplace_back(TASK_CLASS(*cp));
} while (cp.next());
return ret;
......@@ -398,60 +482,129 @@ auto make_task(std::tuple<Elems...>&& t)
template <typename Class>
struct computed_collection : value<std::vector<Class>> {
struct computed_collection : collection<std::vector<Class>> {
typedef std::vector<Class> value_type;
value_type value_cache;
template <typename... Dependencies>
computed_collection(const std::tuple<Dependencies...>& t)
/*: value<std::vector<Class>>({make_task<Class>(t)})*/
: collection<std::vector<Class>>{value_cache}
{
value_cache = make_task<Class>(t);
}
template <typename... Dependencies>
computed_collection(const Dependencies&... deps)
/*: value<std::vector<Class>>({make_task<Class>(t)})*/
: collection<std::vector<Class>>{value_cache}
{
value_cache = make_task<Class>(std::make_tuple(deps...));
}
operator std::vector<Class>& ()
{
return value_cache;
}
size_t size() { return value_cache.size(); }
Class& operator [] (size_t i) { return value_cache[i]; }
static const bool composite = true;
};
#if 0
template <typename Class>
struct computed_collection : collection<std::vector<Class>> {
/*template <typename DepTuple> struct expand_tuple;*/
/*template <typename... Dependencies>*/
/*struct expand_tuple<std::tuple<Dependencies...>> {*/
/*typedef async_computed_value<computed_collection<Class>, std::vector<Class>, Dependencies...>*/
/*};*/
using value<std::vector<Class>>::val;
/*using value<std::vector<Class>>::val;*/
typedef std::vector<typename Class::value_type> value_type;
typedef std::vector<Class> value_type;
value_type value_cache;
template <typename... Dependencies>
struct compute_async
: async_computed_value<compute_async<Dependencies...>,
std::vector<typename Class::value_type>,
std::vector<Class>,
Dependencies...>
{
using async_computed_value<compute_async<Dependencies...>,
std::vector<typename Class::value_type>,
std::vector<Class>,
Dependencies...>::async_computed_value;
virtual std::vector<typename Class::value_type>
std::vector<Class>
do_compute(const Dependencies&... x)
{
std::vector<typename Class::value_type> ret;
for (auto& tsk: make_task<Class>(std::make_tuple(x...))) {
ret.push_back(tsk);
}
return ret;
/*std::vector<Class> ret;*/
/*for (const auto& tsk: make_task<Class>(std::make_tuple(x...))) {*/
/*ret.emplace_back(tsk);*/
/*}*/
/*return ret;*/
return make_task<Class>(std::make_tuple(x...));
}
};
std::function <value_type()> fetch_async;
std::function <void()> destroy_async;
bool fetched;
template <typename... Dependencies>
computed_collection(const std::tuple<Dependencies...>& t)
/*: value<std::vector<Class>>({make_task<Class>(t)})*/
: value<std::vector<Class>>()
: collection<std::vector<Class>>{value_cache}
{
compute_async<Dependencies...>* task = new compute_async<Dependencies...>(t);
fetch_async = [=] () { value_type ret = *task; delete task; return ret; };
fetch_async = [task] () { return task->v(); };
destroy_async = [task] () { delete task; };
fetched = false;
}
operator std::vector<typename Class::value_type> ()
template <typename... Dependencies>
computed_collection(const Dependencies&... deps)
/*: value<std::vector<Class>>({make_task<Class>(t)})*/
: collection<std::vector<Class>>{value_cache}
{
compute_async<Dependencies...>* task = new compute_async<Dependencies...>(deps...);
DEBUG("aync_task @" << task);
fetch_async = [task] () { return task->v(); };
destroy_async = [task] () { delete task; };
fetched = false;
}
std::vector<Class>& __retrieve()
{
DEBUG(__FILE__ << ':' << __LINE__);
if (!fetched) {
DEBUG(__FILE__ << ':' << __LINE__);
value_cache = fetch_async();
DEBUG(__FILE__ << ':' << __LINE__);
destroy_async();
DEBUG(__FILE__ << ':' << __LINE__);
fetched = true;
DEBUG(__FILE__ << ':' << __LINE__);
}
DEBUG(__FILE__ << ':' << __LINE__);
return value_cache;
}
operator std::vector<Class>& ()
{
return __retrieve();
}
size_t size() { return __retrieve().size(); }
Class& operator [] (size_t i) { return __retrieve()[i]; }
static const bool composite = true;
};
#endif
}
#endif
......
......@@ -157,5 +157,25 @@ operator & (cache_input& c, Eigen::Matrix<_Scalar, _Rows, _Cols, _Options, _MaxR
return c;
}
template <typename Class, typename Type, typename... Dependencies>
cache_input&
operator & (cache_input& c, cache::computed_value<Class, Type, Dependencies...>& cv)
{
std::tuple<Dependencies...> dep;
c & dep;
cv.__init(dep);
return c;
}
template <typename Class, typename Type, typename... Dependencies>
cache_output&
operator & (cache_input& c, cache::computed_value<Class, Type, Dependencies...>& cv)
{
c & cv.task->dependencies;
return c;
}
#endif
......@@ -105,6 +105,13 @@ struct md5_digest {
return *this;
}
template <typename T>
md5_digest&
update(const T* ptr)
{
return update(*ptr);
}
template <typename F, typename S>
md5_digest&
update(const std::pair<F, S>& p)
......
......@@ -3,10 +3,31 @@
namespace cache {
template <typename T> struct value;
template <typename T>
struct value_traits {
typedef void operator_bracket_return;
static void helper();
};
template <typename V>
struct value_traits<std::vector<V>> {
typedef value<V> operator_bracket_return;
static operator_bracket_return
helper(const value<std::vector<V>>& v, size_t i)
{
return {v.val[i]};
}
};
template <typename TYPE>
struct value {
typedef value_traits<TYPE> traits;
typedef TYPE value_type;
TYPE val;
struct iterator {
typedef value<TYPE> value_type;
value<TYPE> val;
......@@ -24,7 +45,22 @@ struct value {
iterator begin() const { return {*this}; }
iterator end() const { return {}; }
typedef iterator const_iterator;
operator TYPE () const { return val; }
operator const TYPE& () const { return val; }
const TYPE& v() const { return val; }
value() : val() {}
value(const TYPE& v_) : val(v_) {}
value(TYPE&& v_) : val(v_) {}
template <typename K>
typename traits::operator_bracket_return
operator [] (const K& k) const
{
return traits::helper(*this, k);
}
static const bool composite = false;
};
......@@ -48,6 +84,8 @@ struct range {
typedef iterator const_iterator;
iterator begin() const { return {min}; }
iterator end() const { return {max}; }
static const bool composite = true;
};
......@@ -71,6 +109,8 @@ struct collection {
typedef iterator const_iterator;
iterator begin() const { return {coll.begin()}; }
iterator end() const { return {coll.end()}; }
static const bool composite = true;
};
}
......@@ -84,8 +124,8 @@ std::ostream& operator << (std::ostream& os, const cache::range<V>& r) { return
template <typename V>
std::ostream& operator << (std::ostream& os, const cache::collection<V>& r)
{
auto i = r.val.begin();
auto j = r.val.end();
auto i = r.coll.begin();
auto j = r.coll.end();
if (i == j) {
return os << "{}";
}
......
#ifndef _MCQTL_COMPUTATIONS_H_
#define _MCQTL_COMPUTATIONS_H_
#include "input.h"
#include "settings.h"
#include "cache.h"
namespace computations {
using cache::value;
using cache::range;
using cache::collection;
using cache::computed_value;
using cache::computed_collection;
template <typename _Coll> struct all_keys;
template <typename _Coll> struct all_values;
template <typename K, typename V, typename A, typename C>
struct all_keys<std::map<K, V, A, C>> : collection<std::vector<value<K>>> {
std::vector<value<K>> val;
all_keys(const std::map<K, V, A, C>& map)
: collection<std::vector<value<K>>>{val}
{
for (const auto& kv: map) {
val.emplace_back(kv.first);
}
}
value<K> operator [] (size_t i) { return val[i]; }
size_t size() const { return val.size(); }
};
template <typename K, typename V, typename A, typename C>
struct all_values<std::map<K, V, A, C>> : collection<std::vector<V>> {
std::vector<V> val;
all_values(const std::map<K, V, A, C>& map)
: collection<std::vector<V>>{val}
{
for (auto& kv: map) {
val.push_back(kv.second);
}
}
value<V>& operator [] (size_t i) { return {val[i]}; }
size_t size() const { return val.size(); }
};
}
namespace computations {
#include "computations/from_settings.h"
}
#endif
#ifndef _MCQTL_COMPUTATIONS_FROM_SETTINGS_H_
#define _MCQTL_COMPUTATIONS_FROM_SETTINGS_H_
extern settings_t* active_settings;
struct generation : value<generation_rs*> {
generation() : value<generation_rs*>() {}
generation(const value<std::string>& name)
: value<generation_rs*>{active_settings->design->generation[name]}
{ DEBUG("generation '" << name << "' @" << v()); }
generation(const std::tuple<value<std::string>>& name)
: value<generation_rs*>{active_settings->design->generation[std::get<0>(name)]}
{ DEBUG("generation '" << name << "' @" << v()); }
};
struct chromosome : value<const ::chromosome*> {
::chromosome* _find(const std::string& name)
{
for (auto& chr: active_settings->map) {
if (chr.name == name) {
return &chr;
}
}
return NULL;
}
chromosome(const std::string& name)
: value<const ::chromosome*>{_find(name)}
{}
chromosome(const ::chromosome* chr)
: value<const ::chromosome*>{chr}
{}
};
struct population : value<::population*> {
population(const value<std::string>& name)
: value<::population*>{&active_settings->populations[name]}
{}
};
struct all_observed_generation_names : all_keys<decltype(::population::observed_mark)> {
all_observed_generation_names(const population& pop)
: all_keys<decltype(::population::observed_mark)>(pop.v()->observed_mark)
{}
using all_keys<decltype(::population::observed_mark)>::size;
using all_keys<decltype(::population::observed_mark)>::operator [];
};
struct marker_observations : value<std::vector<char>> {
marker_observations(const population& pop, const chromosome& chr, const value<std::string>& gen, const value<int>& num)
: value<std::vector<char>>{
pop.v()->observed_mark[gen]
.observations