Wednesday, November 21, 2012

movable std::bind with placeholders

And finally the placement compatible version of the movable binder.. from 2012/11/perfect-forwarding-bind-compatable-with.html. this is again using threads to show that it works as with move only objects.

Also this probably needs gcc to work as it has a special placeholder classes call std::_Placeholder<>. Also I had to work around a compiler bug that kills the variadic templates nasty little monster that one..

And I still havent done anything about the problem with copying the binder

Ok this code probably needs a bit of explanation
There are several parts to a binder/lambda
  1. The "Binder Object" this is the main body of the binder. in the following code its called "MovableBinder"
  2. The "Bound function" this is the function that is to be executed in at the later point. In the code below its the typedef or template param called "Func"
  3. The "Closure" this is the part of the binder that captures variables in the context that the binder was created in. In the code below its called "MoveCapture"
  4. The "Placeholder" these are placement markers that allow the parameters that are handed in to be jumbled around for the binding interface. In the below code i attempted to use standard std::placeholders. It hasnt really worked out so great.
  5. The "Parameters" these are the params passed to the bind at the point of its execution. In the following code they are cached into the "MoveHolder" class.
This main core of this code design is the MoveCapture.

On Construction it recurses down the varable param decimates the list to an aggregate object that caches 1 param "A" or the placeholder on each step.

On "call" it again recurses down the MoveCapture structure again but this time its its doing the exact opposite and inductively constructing a list of params into the variadic param list called "InArgs".. If it strikes a placeholder it simple retrieves that entry from the MoveHolders object. By the end of structure it has recreated the full param list for the bound function call.


#include <iostream>
#include <memory>
#include <utility>
#include <tuple>
#include <thread>
#include <functional>
#include <string>

template <typename ...H>
struct MoveHolder 
{
  typedef std::tuple<H...>  Tuple;
  Tuple values_;
  
  MoveHolder(H&& ...h) :
    values_(std::forward<H>(h)...)
  {}

  template <int I>
  typename std::tuple_element<I, Tuple>::type&& access()
  {
    return std::move(std::get<I>(std::move(values_)));
  }
};


template <typename A, typename ...Args> 
struct MoveCapture : public MoveCapture<Args...>
{
  A a_;

  MoveCapture(A&& a, Args&& ...args) :
    MoveCapture<Args...>(std::forward<Args>(args)...),
    a_(std::forward<A>(a))
  {
    std::cout << "DEBUG " << __LINE__ << "\n";
  }

  template <typename Func,
     typename H,
       typename ...InArgs>
  void call(Func& f,
       H&& holders,
       InArgs&& ...args)
  {
    std::cout << "DEBUG " << __LINE__ << "\n";

    MoveCapture<Args...>::call(f, 
          holders,
          std::forward<InArgs>(args)...,
          std::move(a_));
  }
};

template <typename A> 
struct MoveCapture<A>
{
  A a_;

  MoveCapture(A&& a) :
    a_(std::forward<A>(a))
  {
    std::cout << "DEBUG " << __LINE__ << "\n";
  }

  template <typename Func,
     typename H,
       typename ...InArgs>
  void call(Func& f,
       H& holders,
       InArgs&& ...args)
  {
    std::cout << "DEBUG " << __LINE__ << "\n";

    f(std::forward<InArgs>(args)...,
      std::move(a_));
  }
};

template <int I, typename ...Args>
struct MoveCapture<const std::_Placeholder<I>, Args...> : public MoveCapture<Args...>
{
  enum { Index = I };
  
  MoveCapture(const std::_Placeholder<I>& h, Args&& ...args) :
    MoveCapture<Args...>(std::forward<Args>(args)...)
  {
    std::cout << "DEBUG " << __LINE__ << "\n";
  }

  //WARNING complier BUG!
  // COMMENTING THIS WILL CAUSE "call" to fail build
  template <typename H>
  void access(H& holders)
  {
    std::cout << I << "\n";
  }
  //END BUG

  template <typename Func,
     typename H,
       typename ...InArgs>
  void call(Func& f,
       H& holders,
       InArgs&& ...args)
  {
    std::cout << "DEBUG " << __LINE__ << "\n";

    MoveCapture<Args...>::call(f,
          holders,
          std::forward<InArgs>(args)...,
          std::move(holders.access<I-1>()));
  }
};

template <int I>
struct MoveCapture<const std::_Placeholder<I>>
{
  MoveCapture(const std::_Placeholder<I>& h) 
  {
    std::cout << "DEBUG " << __LINE__ << "\n";    
  }

  //WARNING complier BUG!
  // COMMENTING THIS WILL CAUSE "call" to fail build
  template <typename H>
  void access(H& holders)
  {
    std::cout << I << "\n";
  }
  //END BUG

  template <typename Func,
     typename H,
       typename ...InArgs>
  void call(Func& f,
       H& holders,
       InArgs&& ...args)
  {
    std::cout << "DEBUG " << __LINE__ << "\n";

    f(std::forward<InArgs>(args)...,
      std::move(holders.access<(I-1)>()));
  }
};

//template <typename ...P>
template <typename Func, typename Capture>
class MovableBinder
{
private:
  Func func_;
  Capture* capture_;

public:
  MovableBinder(Func func, Capture* cap) :
    func_(func),
    capture_(cap)
  {}

  ~MovableBinder()
  {
    if (capture_!= NULL)
      delete capture_ ;
  }

  template <typename ...V>
  void operator()(V&& ...v)
  {
    std::cout << "DEBUG " << __LINE__ << "\n";
    MoveHolder<V...> holders(std::forward<V>(v)...);
    capture_->call(func_, holders);
  }
};

template <typename ...P>
struct MovableSetup
{
  typedef void (*Func)(P&&...);

  template <typename ...H>
  static MovableBinder<Func,MoveCapture<H...>> setup(Func f, H ...h)
  {
    typedef MoveCapture<H...> Capture;

    std::cout << "DEBUG " << __LINE__ << "\n";
    Capture* capture =  new MoveCapture<H...>(std::forward<H>(h)...);
    return MovableBinder<Func,Capture>(f,capture);
  }
};

void hello(double&& done)
{
  std::cout << done << "\n";
}  

void hello2(double&& done1,
     double&& done2)
{
  std::cout << " part1:" << done1 
     << " part2:" << done2 
     << "\n";
}  

void thread_core() 
{
  std::this_thread::sleep_for(std::chrono::seconds(2));
}

void join_thread(std::thread&& t1)
{
  std::cout << "Joining the thread....\n";
  t1.join();
}

int main()
{
  std::cout << "******** MANUAL USAGE **********\n";
  
  MoveCapture<const std::_Placeholder<1> > capture(std::placeholders::_1);
  MoveHolder<double> param(1.23);
  std::cout << param.access<0>() << "\n";
  
  capture.call(hello, param);
  
  std::cout << "******** NORMAL USAGE *********\n";
  
  auto movable_binder_1a = MovableSetup<double>::setup<const std::_Placeholder<1> >(hello,std::placeholders::_1);
  movable_binder_1a(1.34);

  auto movable_binder_1b = MovableSetup<double>::setup(hello,3.14);
  movable_binder_1b();

  auto movable_binder_2a = 
    MovableSetup<double, double>::setup<const std::_Placeholder<1>,
       const std::_Placeholder<2>>
          (hello2, std::placeholders::_1, std::placeholders::_2);
  movable_binder_2a(4.56,1.37);

  auto movable_binder_2b = 
          MovableSetup<double, double>::setup<double,
           double>
          (hello2,492.54, 743.293);
  movable_binder_2b();

  auto movable_binder_2c = 
          MovableSetup<double, double>::setup<double,
       const std::_Placeholder<2>>
          (hello2,492.54, std::placeholders::_2);
  movable_binder_2c(4.56,1.37);  //trash param 1

  std::cout << "******** THREAD BIND USAGE *********\n";

  std::thread tc(thread_core);
  auto movable_binder_tc = 
    MovableSetup<std::thread>::setup(join_thread, std::move(tc));
  movable_binder_tc();

  std::thread td(thread_core);
  auto movable_binder_td = 
    MovableSetup<std::thread>::setup<const std::_Placeholder<1> >(join_thread, std::placeholders::_1);
  movable_binder_td(std::move(td));

}

Tuesday, November 13, 2012

perfect forwarding std::bind replacement compatable with std::move

And without any more messing around here is the generic version of the movable std::bind replacement.

  1. This version doesnt handle place holders yet.
  2. There is probably problems if you try to copy it
Update: I since added a placeholder version here
#include <iostream>
#include <memory>
#include <utility>
#include <thread>

//A helper class for storage and stitching params together
template <typename A, typename ...Args> 
struct MoveHelper : public MoveHelper<Args...>
{
  A a_;

  MoveHelper(A&& a, Args&& ...args) :
    MoveHelper<Args...>(std::forward<Args>(args)...),
    a_(std::forward<A>(a))
  {}

  template <typename Func, typename ...InArgs>
  void call(Func& f, InArgs && ...args)
  {
    MoveHelper<Args...>::call(f,
         std::forward(args)..., 
         std::move(a_));
  }
};

//The helpers terminal case
template <typename A> 
struct MoveHelper<A>
{
  A a_;

  MoveHelper(A&& a) :
    a_(std::forward<A>(a))
  {}

  template <typename Func, typename ...InArgs>
  void call(Func& f, InArgs && ...args)
  {
    f(std::forward<A>(args)...,
      std::forward<A>(a_));
  }
};

//the Main std::bind movable replacement
template <typename ...P>
class MovableBinder
{
  typedef void (*F)(P&&...);

private:
  F func_;
  MoveHelper<P...> help_;

public:
  MovableBinder(F func, P&& ...p) :
    func_(func),
    help_(std::forward<P>(p)...)
  {}

  MovableBinder(F func, P& ...p) :
    func_(func),
    help_(p...)
  {}
    
  ~MovableBinder()
  {}

  void operator()()
  {
    help_.call(func_);
  }
};

//And the test with threads.. the ultimate move only object...

void thread_core() {
  std::this_thread::sleep_for(std::chrono::seconds(2));
}

void join_thread(std::thread&& t1)
{
  std::cout << "Joining the thread....\n";
  t1.join();
}  

void join_threads(std::thread&& t1, std::thread&& t2)
{
  std::cout << "Joining the threads....\n";
  t1.join();
  t2.join();
}  

int main()
{
  std::thread ta(thread_core);
  std::thread tb(thread_core);
  MovableBinder<std::thread, std::thread> movable_binder_threads(&join_threads, std::move(ta),std::move(tb));

  movable_binder_threads();

  std::thread tc(thread_core);
  MovableBinder<std::thread> movable_binder_thread(&join_thread, std::move(tc));

  movable_binder_thread();

}

c++11 Variadic template expansion options

While hacking up this movable bind function I got distracted(as per usual) thinking about the range of possible variadic template expansions available to us.

I figure that there are 2 main choices to make when using the argument packed types.
  1. Argument expansion or Argument Recursion
  2. Direct or Indirect

Argument expansion is where you flatten out the argument with the .... and pass them on.
  • The direct form of this is to work the expansion on the Argument is self.
  • The indirect for is to use a helper function around the Argument and expand the function passing it each object.

Argument recursion is where you siphon off one or more arguments on each pass and call down into your templates for the next stage.

  • The direct form is to do this in your main struct or function
  • The indirect form of this is where you create an inner helper or core that handles the recursive part for you.

Heres a triplet of examples that show the main uses cases that I would expect to see.. I guess there might be more but nothing else comes to mind at the moment... 
#include <iostream>
#include <utility>

// Indirect recursive class expansion
template <typename Func, typename A, typename ...Args> 
struct CallForEachHelper
{
  static void call(Func & f, A && a, Args && ...args)
  {
    f(std::forward<A>(a));
    CallForEachHelper<Func, Args...>::call(f, args...);
  }
};

template <typename Func, typename A> 
struct CallForEachHelper<Func, A>
{
  static void call(Func & f, A && a)
  {
    f(std::forward<A>(a));
  }
};

template <typename Func, typename ...Args>
void CallForEachIndirect(Func & f, Args && ...args)
{
  CallForEachHelper<Func, Args...>::call(f, std::forward<Args>(args)...);
}

// Direct recursive function expansion
template <typename Func, typename Arg>
void CallForEachDirect(Func & f, Arg arg)
{
  f(std::forward<Arg>(arg));
}

template <typename Func, typename Arg, typename ...Args>
void CallForEachDirect(Func & f, Arg arg, Args && ...args)
{
  f(std::forward<Arg>(arg));
  CallForEachDirect<Func, Args...>(f, std::forward<Args>(args)...);
}

// direct non-recursive argument flattening
template <typename Func, typename ...Args>
void CallForAll(Func & f, Args && ...args)
{
  f(std::forward<Args>(args)...); //indirect argument flattening using std::forward
}

void foo(int a)
{
  std::cout << "a:" << a << "\n";
}

void foo3(int a, int b, int c)
{
  std::cout << "a:" << a 
     << " b:" << b
     << " c:" << c 
     << "\n";
}

int main()
{
  int a1=1;
  int a2=2;
  int a3=3;
    
  CallForEachIndirect(foo, a1, a2, a3);  // run foo on each item via helper class recursion
  CallForEachDirect(foo, a1, a2, a3);    // run foo on each item by direct recursion
  CallForAll(foo3, a1, a2, a3);          // run foo3 on all items in 1 shot.
}

Sunday, November 11, 2012

perfect forwarding std::bind - why is std::bind not compatable with std::move??

Update: I have since posted the generic form of this code over Here

This is another oddity in the new spec. the std::bind and lambda are not able to take std:move()'ed items. The crazy part is that the standards community went so far as to define a std::forward to achieve perfect forwarding and didn't even take the next logical step and create a perfect forwarding version of std::bind and lamba...

So I hacked up a perfect forwarding verion of std::bind. This version is the one parameter version of the perfect forwarding std::bind. Still working on the variadic template version for unlimited params.

#include <iostream>
#include <memory>
#include <utility>

class MoveOnlyObj
{
public:
  MoveOnlyObj(int val) :
  val_(val)
  {
    std::cout << "MoveOnlyObj() - " << val_ << "\n";
  }
  
  MoveOnlyObj(MoveOnlyObj&& obj) :
  val_(obj.val_)
  {
    std::cout << "MoveOnlyObj(&&) - " << val_ << "\n";
    obj.val_ = 0; //0 it to make it very visable
  }

  ~MoveOnlyObj()
  {
    std::cout << "~MoveOnlyObj - " << val_ << "\n";
  }

private:
  friend std::ostream& operator<<(std::ostream& out, const MoveOnlyObj& o);
  MoveOnlyObj(MoveOnlyObj& obj);
  
  int val_;
};

std::ostream& operator<<(std::ostream& out, const MoveOnlyObj& o)
{
  out << o.val_;
  return out;
}

  
//lets start with the basic
template <typename P>
class MovableBinder1
{
  typedef void (*F)(P&&);

private:
  F func_;
  P p0_;

public:
  MovableBinder1(F func, P&& p) :
    func_(func),
    p0_(std::forward<P>(p))
  {
    std::cout << "Moved" << p0_ << "\n";
  }

  MovableBinder1(F func, P& p) :
    func_(func),
    p0_(p)
  {
    std::cout << "Copied" << p0_ << "\n";
  }
    
  ~MovableBinder1()
  {
    std::cout << "~MovableBinder1\n";
  }

  void operator()()
  {
    (*func_)(std::forward<P>(p0_));
  }
};

void test_func(int&& i)
{
  std::cout << "test_func: " << i << "\n";
}

void move_func(MoveOnlyObj&& i)
{
  MoveOnlyObj taker(std::move(i));
  std::cout << "move_func: " << taker << "\n";
}

int main()
{
  MovableBinder1<int> movable_binder_1_rvalue(&test_func, 3);
  movable_binder_1_rvalue();

  int i=4;
  MovableBinder1<int> movable_binder_1_lvalue(&test_func, i);
  movable_binder_1_lvalue();

  MoveOnlyObj m(5);
  MovableBinder1<MoveOnlyObj> movable_binder_move_only(&move_func, std::move(m));
  movable_binder_move_only();
}

And the output looks like this:
Moved3
test_func: 3
Copied4
test_func: 4
MoveOnlyObj() - 5
MoveOnlyObj(&&) - 5
Moved5
MoveOnlyObj(&&) - 5
move_func: 5
~MoveOnlyObj - 5
~MovableBinder1
~MoveOnlyObj - 0
~MoveOnlyObj - 0
~MovableBinder1
~MovableBinder1


And here is the gripper... This one passes a thread in as the parameter..
#include <iostream>
#include <memory>
#include <utility>
#include <thread>

//lets start with the basic
template <typename P>
class MovableBinder1
{
  typedef void (*F)(P&&);

private:
  F func_;
  P p0_;

public:
  MovableBinder1(F func, P&& p) :
    func_(func),
    p0_(std::forward<P>(p))
  {}

  MovableBinder1(F func, P& p) :
    func_(func),
    p0_(p)
  {}
    
  ~MovableBinder1()
  {}

  void operator()()
  {
    (*func_)(std::forward<P>(p0_));
  }
};

void thread_core() 
{
  std::this_thread::sleep_for(std::chrono::seconds(3));
}

void join_thread(std::thread&& t)
{
  std::cout << "Joining the thread....\n";
  t.join();
}  

int main()
{
  std::thread t(thread_core);
  MovableBinder1<std::thread> movable_binder_thread(&join_thread, std::move(t));

  movable_binder_thread();
}

Thursday, November 8, 2012

What is std::async ?

The new C++0x standard has provided many new and powerful tools for a c++ coders arsenal. Unfortunately I have already started to see several cases of copy the book coding. It is all to easy to forget that these tools are just slightly more complex constructs of the more fundamental units.

It is often a very enlightening experience to reinvent the wheel and understand what the original creators had to go through. Rather than just being another just another fool "standing on the shoulders of giants". Just another one of the new generation of school kids that cant add numbers together without a calculator.

So on that note i got curious about how the std::async works. On the surface its seems rather simple, but to actually create it I took several wrong turns. and learned a bit on the way.

There are several lessons that got me here:
* Look carefully at the the Lambda(and also a std::bind) and note that it cant take move schematics. As a result the promise is on the heap and a pointer...
* Note that my imatate_async requires the template param to be filled in. I have missed some trick that the std::async has that allows it to deduce the actual return type of the function.
* Note that this version doesn't account for parameters being passed to the thread function... Im lazy get over it.
* Note the exception catch a generic ... with a std:: function to pull down the actual throw. otherwise you up for std::terminate killing your app when that unexpected throw comes out.. its a bonus that this is a nice way to pass the exception to a different stack.

#include <iostream>
#include <thread>
#include <future>

// thread vs async.

int test_func() 
{
  return 1; 
}

template< class R >
std::future<R> async_imitate(std::function<R(void)> func)
{ 
  std::promise<R>* p = new std::promise<R>();

  std::function<void(void)> wrapper = 
    [p,func]()->void
    {
      try
 {
   p->set_value(func());
 }
      catch(...)
 {
   p->set_exception(std::current_exception());
 }
      delete p;
    };

  std::thread t(wrapper);
  t.detach();
  return p->get_future();
}

void run_thread()
{
  std::cout << "start run_thread\n";
  
  std::future<int> ret = async_imitate<int>(&test_func);
  int i = ret.get();
  std::cout << "run_thread: " << i << "\n";
}

void run_async()
{
  std::cout << "start run_async\n";

  std::future<int> ret = std::async(&test_func);
  int i = ret.get();
  std::cout << "run_async: " << i << "\n";
}

int main()
{
  run_async();
  run_thread();
}