Commit 8a296073 authored by Damien Leroux's avatar Damien Leroux
Browse files

Caching system works with basic functionality.

parent 5b6ac72a
#ifndef _MCQTL_3RD_PARTY_TUPLE_CALL_CODE_H_
#define _MCQTL_3RD_PARTY_TUPLE_CALL_CODE_H_
/* from http://stackoverflow.com/a/10766422 */
// implementation details, users never invoke these directly
namespace detail
{
template <typename F, typename Tuple, bool Done, int Total, int... N>
struct call_impl
{
static void call(F f, Tuple && t)
{
call_impl<F, Tuple, Total == 1 + sizeof...(N), Total, N..., sizeof...(N)>::call(f, std::forward<Tuple>(t));
}
};
template <typename F, typename Tuple, int Total, int... N>
struct call_impl<F, Tuple, true, Total, N...>
{
static void call(F f, Tuple && t)
{
f(std::get<N>(std::forward<Tuple>(t))...);
}
};
}
// user invokes this
template <typename F, typename Tuple>
void call(F f, Tuple && t)
{
typedef typename std::decay<Tuple>::type ttype;
detail::call_impl<F, Tuple, 0 == std::tuple_size<ttype>::value, std::tuple_size<ttype>::value>::call(f, std::forward<Tuple>(t));
}
#endif
#ifndef _MCQTL_CACHE_CARTESIAN_PRODUCT_H_
#define _MCQTL_CACHE_CARTESIAN_PRODUCT_H_
namespace cache {
template <typename ITEM>
using item_iterator = typename ITEM::iterator;
template <typename ITEM>
struct iterator_context {
typedef item_iterator<ITEM> iterator;
item_iterator<ITEM> begin, end, cursor;
iterator_context() : begin(), end(), cursor() {}
iterator_context(const ITEM& i)
: begin(i.begin()), end(i.end()), cursor(i.begin())
{}
iterator_context(const iterator_context<ITEM>& ic)
: begin(ic.begin), end(ic.end), cursor(ic.cursor)
{}
iterator_context<ITEM>& operator = (const iterator_context<ITEM>& i)
{
begin = i.begin;
end = i.end;
cursor = i.cursor;
}
bool next() { ++cursor; if (cursor == end) { cursor = begin; return true; } return false; }
typename item_iterator<ITEM>::value_type operator * () const { return *cursor; }
};
template <typename Item>
struct do_next {
typedef bool return_type;
bool operator () (Item& i) const
{
return i.next();
}
};
template <typename Item>
struct do_get {
typedef typename std::remove_const<typename std::remove_reference<typename item_iterator<Item>::value_type>::type>::type return_type;
return_type operator () (const Item& i) const
{
return *i;
}
};
template <typename... ITEMS>
struct cartesian_product {
typedef typename make_sequence<sizeof...(ITEMS)>::type indices;
template <typename X> struct to_bool { typedef bool type; };
std::tuple<iterator_context<ITEMS>...> iter;
bool at_end;
cartesian_product() : iter(), at_end(true) {}
cartesian_product(const ITEMS&... x)
: iter(x...), at_end(false)
{}
cartesian_product(const std::tuple<ITEMS...>& x)
: iter(x), at_end(false)
{}
cartesian_product(const cartesian_product<ITEMS...>& cp)
: iter(cp.iter), at_end(cp.at_end)
{}
cartesian_product<ITEMS...>& operator = (const cartesian_product& cp)
{
iter = cp.iter;
at_end = cp.at_end;
return *this;
}
typedef typename indices::template with_backward_recursion<do_next, iterator_context<ITEMS>...> nexter;
typedef typename indices::template with_processor<do_get, iterator_context<ITEMS>...> getter;
bool next()
{
if (!at_end) {
at_end = nexter::process(iter);
}
return !at_end;
}
std::tuple<typename item_iterator<ITEMS>::value_type...> operator * () const
{
if (!at_end) {
return getter::process(iter);
}
throw 0;
}
struct iterator {
typedef std::tuple<typename item_iterator<ITEMS>::value_type...> value_type;
cartesian_product<ITEMS...> cp;
value_type operator * () const { return *cp; }
iterator& operator ++ () { cp.next(); }
iterator& operator ++ (int) { cp.next(); }
bool operator == (const iterator& i) { return i.cp.at_end && cp.at_end; }
bool operator != (const iterator& i) { return !(*this == i); }
};
cartesian_product<ITEMS...> copy() const
{
cartesian_product<ITEMS...> ret;
ret.iter = iter;
ret.at_end = at_end;
return ret;
}
iterator begin() { std::cout << "BEGIN" << std::endl; return {*this}; }
iterator end() { std::cout << "END" << std::endl; return {{}}; }
};
}
#endif
This diff is collapsed.
#ifndef _MCQTL_CACHE_FILE_H_
#define _MCQTL_CACHE_FILE_H_
#include <iostream>
#include <type_traits>
struct cache_input_traits {
typedef std::istream stream_type;
static void op(stream_type& st, char* b, size_t sz) { st.read(b, sz); }
};
struct cache_output_traits {
typedef std::ostream stream_type;
static void op(stream_type& st, char* b, size_t sz) { st.write(b, sz); }
};
template <typename CACHE_DIRECTION>
struct cache_file {
typename CACHE_DIRECTION::stream_type& f;
cache_file(typename CACHE_DIRECTION::stream_type& _) : f(_) {}
operator typename CACHE_DIRECTION::stream_type& () { return f; }
cache_file<CACHE_DIRECTION>& op(char* b, size_t sz)
{
CACHE_DIRECTION::op(f, b, sz);
return *this;
}
};
typedef cache_file<cache_input_traits> cache_input;
typedef cache_file<cache_output_traits> cache_output;
template <typename CACHE_DIRECTION, typename X>
cache_file<CACHE_DIRECTION>&
operator & (cache_file<CACHE_DIRECTION>& c, X& x)
{
return c.op(reinterpret_cast<char*>(&x), sizeof(X));
}
#if 0
template <typename CACHE_DIRECTION, typename X>
typename std::enable_if<!std::is_arithmetic<X>::value,
cache_file<CACHE_DIRECTION>>::type&
operator & (cache_file<CACHE_DIRECTION>& c, const X& x)
{
return c.op(reinterpret_cast<char*>(&x), sizeof(X));
}
template <typename CACHE_DIRECTION, typename X>
typename std::enable_if<std::is_arithmetic<X>::value,
cache_file<CACHE_DIRECTION>>::type&
operator & (cache_file<CACHE_DIRECTION>& c, X x)
{
CACHE_DIRECTION::op(c, reinterpret_cast<char*>(&x), sizeof(X));
}
#endif
cache_output& operator & (cache_output& c, const std::string& s)
{
size_t sz = s.size();
c & sz;
return c.op(const_cast<char*>(s.c_str()), s.size());
}
cache_input& operator & (cache_input& c, std::string& s)
{
std::cout << __FILE__ << ':' << __LINE__ << '@' << __func__ << std::endl;
size_t sz = 0;
std::cout << __FILE__ << ':' << __LINE__ << '@' << __func__ << std::endl;
c & sz;
std::cout << __FILE__ << ':' << __LINE__ << '@' << __func__ << std::endl;
std::cout << " sz=" << sz << std::endl;
s.resize(sz, ' ');
std::cout << __FILE__ << ':' << __LINE__ << '@' << __func__ << std::endl;
return c.op(const_cast<char*>(s.c_str()), sz);
}
#endif
#ifndef _MCQTL_MD5_H_
#define _MCQTL_MD5_H_
#include <iostream>
#include <utility>
#include <string>
#include <sstream>
#include <iomanip>
#include <tuple>
#include <openssl/evp.h>
namespace detail {
......@@ -90,7 +92,7 @@ struct md5_digest {
typename std::enable_if<detail::is_container<T>::value, md5_digest>::type&
update(const T& t)
{
for (auto& k: t) {
for (const auto& k: t) {
update(k);
}
return *this;
......
#ifndef _MCQTL_CACHE_TUPLE_UTILS_H_
#define _MCQTL_CACHE_TUPLE_UTILS_H_
#include <tuple>
namespace cache {
template <int... X> struct reverse;
template <typename Reverse, int... X> struct reverse_impl;
template <int... REV, int CAR, int... CDR>
struct reverse_impl<reverse<REV...>, CAR, CDR...> {
typedef typename reverse_impl<reverse<CAR, REV...>, CDR...>::type type;
};
template <int... REV>
struct reverse_impl<reverse<REV...>> { typedef reverse<REV...> type; };
template <int... X>
struct make_reverse { typedef typename reverse_impl<reverse<>, X...>::type type; };
template <template <typename X> class PREDICATE, typename... T> struct if_any_type;
template <template <typename X> class PREDICATE, typename X>
struct if_any_type<PREDICATE, X> {
static const bool value = PREDICATE<X>::value;
};
template <template <typename X> class PREDICATE, typename CAR, typename... CDR>
struct if_any_type<PREDICATE, CAR, CDR...> {
static const bool value = PREDICATE<CAR>::value || if_any_type<PREDICATE, CDR...>::value;
};
template <int... Indices> struct sequence {
template <template <typename X> class PROCESSOR, typename... TupleElems>
struct with_processor {
typedef std::tuple<typename PROCESSOR<TupleElems>::return_type...> result_type;
static result_type process(const std::tuple<TupleElems...>& x)
{
return std::make_tuple(PROCESSOR<TupleElems>()(std::get<Indices>(x))...);
}
static result_type process(std::tuple<TupleElems...>& x)
{
return std::make_tuple(PROCESSOR<TupleElems>()(std::get<Indices>(x))...);
}
};
template <template <typename X> class PROCESSOR, typename... TupleElems>
struct with_processor<PROCESSOR, std::tuple<TupleElems...>> : public with_processor<PROCESSOR, TupleElems...> {};
template <template <typename X> class PROCESSOR, typename... TupleElems>
struct with_backward_recursion {
typedef bool result_type;
typedef typename make_reverse<Indices...>::type backward_indices;
template <typename REV, typename... ELEMENTS> struct backward;
template <typename REV> struct backward_tuple;
template <int I, int... BackwardIndices, typename Elem, typename... Elems>
struct backward<reverse<I, BackwardIndices...>, Elem, Elems...> {
static bool process(Elem& car, Elems&... x)
{
if (PROCESSOR<Elem>()(car)) {
return backward<reverse<BackwardIndices...>, Elems...>::process(x...);
}
return false;
}
};
template <int I, typename Elem>
struct backward<reverse<I>, Elem> {
static bool process(Elem& car)
{
return PROCESSOR<Elem>()(car);
}
};
template <int I, int... BackwardIndices>
struct backward_tuple<reverse<I, BackwardIndices...>> {
static bool process(std::tuple<TupleElems...>& x)
{
if (PROCESSOR<typename std::tuple_element<I, std::tuple<TupleElems...>>::type>()(std::get<I>(x))) {
return backward_tuple<reverse<BackwardIndices...>>::process(x);
}
}
};
template <int I>
struct backward_tuple<reverse<I>> {
static bool process(std::tuple<TupleElems...>& x)
{
return PROCESSOR<typename std::tuple_element<I, std::tuple<TupleElems...>>::type>()(std::get<I>(x));
}
};
static bool process(TupleElems&... x)
{
return backward<backward_indices, TupleElems...>::process(x...);
}
static bool process(std::tuple<TupleElems...>& x)
{
return backward_tuple<backward_indices>::process(x);
}
};
};
template <int N, int Last, int... Indexes>
struct make_sequence_impl {
typedef typename std::enable_if<N != Last,
typename make_sequence_impl<N, Last + 1, Indexes..., Last>::type
>::type type;
};
template <int N, int... Indexes>
struct make_sequence_impl<N, N, Indexes...> {
typedef sequence<Indexes...> type;
};
template <int N> struct make_sequence { typedef typename make_sequence_impl<N, 0>::type type; };
template <template <typename ITEM> class TRANSFORM, typename... TupleElems>
struct transform {
typedef typename make_sequence<sizeof...(TupleElems)>::type indices;
typedef typename indices::template with_processor<TRANSFORM, TupleElems...> processor;
typedef typename processor::result_type type;
type operator () (TupleElems... x) const
{
return processor::process(x...);
}
};
}
#endif
#ifndef _MCQTL_CACHE_VALUE_H_
#define _MCQTL_CACHE_VALUE_H_
namespace cache {
template <typename TYPE>
struct value {
typedef TYPE value_type;
TYPE val;
struct iterator {
typedef value<TYPE> value_type;
value<TYPE> val;
bool end;
iterator(const value<TYPE>& v) : val(v), end(false) {}
iterator() : val(), end(true) {}
iterator(const iterator& i) : val(i.val), end(i.end) {}
value_type operator * () const { return val; }
iterator& operator ++ () { end = true; return *this; }
iterator& operator ++ (int) { end = true; return *this; }
bool operator != (const iterator& i) const { return end != i.end; }
bool operator == (const iterator& i) const { return end == i.end; }
iterator& operator = (const iterator& i) { val = i.val; end = i.end; }
};
iterator begin() const { return {*this}; }
iterator end() const { return {}; }
typedef iterator const_iterator;
operator TYPE () const { return val; }
};
template <typename INT_TYPE>
struct range {
typedef INT_TYPE value_type;
INT_TYPE min, max;
struct iterator {
typedef value<INT_TYPE> value_type;
INT_TYPE cursor;
iterator() : cursor(0) {}
iterator(INT_TYPE i) : cursor(i) {}
iterator(const iterator& i) : cursor(i.cursor) {}
value_type operator * () const { return {cursor}; }
iterator& operator ++ () { ++cursor; return *this; }
iterator& operator ++ (int) { ++cursor; return *this; }
bool operator != (const iterator& i) const { return cursor != i.cursor; }
bool operator == (const iterator& i) const { return cursor == i.cursor; }
iterator& operator = (const iterator& i) { cursor = i.cursor; }
};
typedef iterator const_iterator;
iterator begin() const { return {min}; }
iterator end() const { return {max}; }
};
template <typename COLL_TYPE>
struct collection {
typedef typename COLL_TYPE::value_type value_type;
const COLL_TYPE& coll;
struct iterator {
typedef value<typename COLL_TYPE::value_type> value_type;
typename COLL_TYPE::const_iterator cursor;
iterator() : cursor() {}
iterator(const typename COLL_TYPE::const_iterator& i) : cursor(i) {}
iterator(const iterator& i) : cursor(i.cursor) {}
value_type operator * () const { return {*cursor}; }
iterator& operator ++ () { ++cursor; return *this; }
iterator& operator ++ (int) { ++cursor; return *this; }
bool operator != (const iterator& i) const { return cursor != i.cursor; }
bool operator == (const iterator& i) const { return cursor == i.cursor; }
iterator& operator = (const iterator& i) { cursor = i.cursor; }
};
typedef iterator const_iterator;
iterator begin() const { return {coll.begin()}; }
iterator end() const { return {coll.end()}; }
};
}
#endif
......@@ -11,32 +11,59 @@ extern "C" {
#include "error.h"
struct file_stat {
bool exists;
int err;
bool is_file;
bool is_dir;
bool writable;
bool readable;
file_stat(const std::string& path)
{
struct stat st;
if (stat(path.c_str(), &st)) {
exists = false;
err = errno;
} else {
exists = true;
err = 0;
}
if (exists) {
is_file = !!S_ISREG(st.st_mode);
is_dir = !!S_ISDIR(st.st_mode);
writable = !!(st.st_mode & (S_IWUSR | S_IWGRP | S_IWOTH));
readable = !!(st.st_mode & (S_IRUSR | S_IRGRP | S_IROTH));
}
}
};
static inline
bool check_file(const std::string& path, bool req_directory, bool req_writable)
{
struct stat st;
if (stat(path.c_str(), &st)) {
file_stat fs(path);
if (fs.err != 0) {
ERROR("Error occurred trying to stat " << path << ": " << strerror(errno), "Check whether " << path << " exists and is accessible");
return false;
}
bool req_dir_ok = req_directory ? S_ISDIR(st.st_mode) : S_ISREG(st.st_mode);
bool req_rd_ok = st.st_mode & (S_IRUSR | S_IRGRP | S_IROTH);
bool req_wr_ok = st.st_mode & (S_IWUSR | S_IWGRP | S_IWOTH);
if (!req_dir_ok) {
if (req_directory) {
ERROR(path << " is not a directory", "Specify the path to directory, not a file [" << path << ']');
} else {
if (req_directory && !fs.is_dir) {
ERROR(path << " is not a directory", "Specify the path to directory, not a file [" << path << ']');
return false;
} else if (!fs.is_file) {
ERROR(path << " is not a regular file or a symbolic link to a regular file", "Specify the path to a file, not a directory [" << path << ']');
}
return false;
}
if (!req_rd_ok) {
if (!fs.readable) {
ERROR(path << " is not readable", "Verify the permissions of " << path);
return false;
}
if (!req_wr_ok) {
if (req_writable && !fs.writable) {
ERROR(path << " is not writable", "Verify the permissions of " << path);
return false;
}
return req_dir_ok && req_rd_ok && req_wr_ok;
return true;
}
#include "input/input.h"
......
......@@ -139,9 +139,9 @@ namespace read_data {
}
#if 0
/*template <typename IStream>*/
#define IStream std::istream
#if 0
inline IStream& operator >> (IStream&& is, haplo_type& h)
{
h.first = is.get();
......
......@@ -3,6 +3,15 @@
using namespace cache;
struct product : cache::computed_value<double, value<double>, value<double>> {
using cache::computed_value<double, value<double>, value<double>>::computed_value;
double compute(const value<double>& d1, const value<double>& d2)
{
return d1 * d2;
}
};
struct task {
typedef std::tuple<value<int>, value<int>, value<char>> tuple_type;
tuple_type _;
......@@ -28,6 +37,14 @@ int main(int argc, char** argv)
std::cout << std::endl;
auto y = make_task<task>(z[0]._);
value<double> a {5};
value<double> b {37};
product p(a, b);
/*std::cout << "filename " << p.cache_filename() << std::endl;*/
/*std::cout << "dependencies digest " << p.dependencies_digest() << std::endl;*/
double res = p;
std::cout << res << std::endl;
#if 0
cartesian_product<value<int>, range<int>, collection<std::vector<char>>> cp(x);
......
Supports Markdown
0%