Listing 4: Wrapping more arguments

template <typename Arg1, typename Arg2>
class FunWrapper2 {
    struct Data : public FunData {
      typedef void (*FunPtr) (Arg1, Arg2);
      Data (FunPtr fun_ptr, Arg1 arg1, Arg2 arg2)  
              : FunData (&Data::thread_entry_point),
                fun_ptr (fun_ptr),
                arg1 (arg1), arg2(arg2)  {};
        private:
      FunPtr fun_ptr;
      Arg1   arg1;
      Arg2   arg2;
      static void * thread_entry_point (void *arg);
    };
    
  public:
    typedef void (*FunPtr) (Arg1, Arg2);

    FunWrapper2 (FunPtr fun_ptr) : fun_ptr(fun_ptr) {};

    Thread operator() (Arg1 arg1, Arg2 arg2) {
      Data data(fun_ptr, arg1, arg2);
      Thread t = do_spawn (data);
      data.lock.acquire ();
      return t;
    };
    
  private:
    FunPtr fun_ptr;
};


template <typename Arg1, typename Arg2>
void * 
FunWrapper2<Arg1,Arg2>::Data::thread_entry_point (void *arg)  {
  const Data *fun_data = reinterpret_cast<const Data*> (arg);
  FunPtr fun_ptr = fun_data->fun_ptr;
  Arg1   arg1    = fun_data->arg1;
  Arg2   arg2    = fun_data->arg2;

  fun_data->lock.release ();

  (*fun_ptr)(arg1, arg2);
  
  return 0;
}


template <typename Arg1, typename Arg2>
FunWrapper2<Arg1,Arg2> spawn (void (*fun_ptr)(Arg1, Arg2)) {
  return FunWrapper2<Arg1,Arg2>(fun_ptr);
}

— End of Listing —