text: #ifndef method_thread_h
  #define method_thread_h
  
  // method_thread(): start a thread that runs an object method.
  // returns a pthread_t on success, and zero on error.
  
  #include <assert.h>
  #include <pthread.h>
  #include <stdio.h>
  #include <string.h>
  #include <stdlib.h>
  
  static pthread_t
  method_thread_parent(void *(*fn)(void *), void *arg, bool detach)
  {
    pthread_t th;
    int err = pthread_create(&th, NULL, fn, arg);
    if(err != 0){
      fprintf(stderr, "pthread_create ret %d %s\n", err, strerror(err));
      exit(1);
    }
  
    if(detach){
      // don't keep thread state around after exit, to avoid
      // running out of threads. set detach==false if you plan
      // to pthread_join.
      assert(pthread_detach(th) == 0);
    }
  
    return th;
  }
  
  static void
  method_thread_child()
  {
    // defer pthread_cancel() by default. check explicitly by
    // enabling then pthread_testcancel().
    int oldstate, oldtype;
    assert(pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate) == 0);
    assert(pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &oldtype) == 0);
  }
  
  template <class C> pthread_t 
  method_thread(C *o, bool detach, void (C::*m)())
  {
    class XXX {
    public:
      C *o;
      void (C::*m)();
      static void *yyy(void *vvv) {
        XXX *x = (XXX*)vvv;
        C *o = x->o;
        void (C::*m)() = x->m;
        delete x;
        method_thread_child();
        (o->*m)();
        return 0;
      }
    };
    XXX *x = new XXX;
    x->o = o;
    x->m = m;
    return method_thread_parent(&XXX::yyy, (void *) x, detach);
  }
  
  template <class C, class A> pthread_t
  method_thread(C *o, bool detach, void (C::*m)(A), A a)
  {
    class XXX {
    public:
      C *o;
      void (C::*m)(A a);
      A a;
      static void *yyy(void *vvv) {
        XXX *x = (XXX*)vvv;
        C *o = x->o;
        void (C::*m)(A ) = x->m;
        A a = x->a;
        delete x;
        method_thread_child();
        (o->*m)(a);
        return 0;
      }
    };
    XXX *x = new XXX;
    x->o = o;
    x->m = m;
    x->a = a;
    return method_thread_parent(&XXX::yyy, (void *) x, detach);
  }
  
  template <class C, class A1, class A2> pthread_t
  method_thread(C *o, bool detach, void (C::*m)(A1 , A2 ), A1 a1, A2 a2)
  {
    class XXX {
    public:
      C *o;
      void (C::*m)(A1 a1, A2 a2);
      A1 a1;
      A2  a2;
      static void *yyy(void *vvv) {
        XXX *x = (XXX*)vvv;
        C *o = x->o;
        void (C::*m)(A1 , A2 ) = x->m;
        A1 a1 = x->a1;
        A2 a2 = x->a2;
        delete x;
        method_thread_child();
        (o->*m)(a1, a2);
        return 0;
      }
    };
    XXX *x = new XXX;
    x->o = o;
    x->m = m;
    x->a1 = a1;
    x->a2 = a2;
    return method_thread_parent(&XXX::yyy, (void *) x, detach);
  }
  
  template <class C, class A1, class A2, class A3> pthread_t
  method_thread(C *o, bool detach, void (C::*m)(A1 , A2, A3 ), A1 a1, A2 a2, A3 a3)
  {
    class XXX {
    public:
      C *o;
      void (C::*m)(A1 a1, A2 a2, A3 a3);
      A1 a1;
      A2  a2;
      A3 a3;
      static void *yyy(void *vvv) {
        XXX *x = (XXX*)vvv;
        C *o = x->o;
        void (C::*m)(A1 , A2 , A3 ) = x->m;
        A1 a1 = x->a1;
        A2 a2 = x->a2;
        A3 a3 = x->a3;
        delete x;
        method_thread_child();
        (o->*m)(a1, a2, a3);
        return 0;
      }
    };
    XXX *x = new XXX;
    x->o = o;
    x->m = m;
    x->a1 = a1;
    x->a2 = a2;
    x->a3 = a3;
    return method_thread_parent(&XXX::yyy, (void *) x, detach);
  }
  
  template <class C, class A1, class A2, class A3, class A4> pthread_t
  method_thread(C *o, bool detach, void (C::*m)(A1 , A2, A3, A4), A1 a1, A2 a2, A3 a3, A4 a4)
  {
    class XXX {
    public:
      C *o;
      void (C::*m)(A1 a1, A2 a2, A3 a3, A4 a4);
      A1 a1;
      A2  a2;
      A3 a3;
      A4 a4;
      static void *yyy(void *vvv) {
        XXX *x = (XXX*)vvv;
        C *o = x->o;
        void (C::*m)(A1 , A2 , A3 , A4) = x->m;
        A1 a1 = x->a1;
        A2 a2 = x->a2;
        A3 a3 = x->a3;
        A4 a4 = x->a4;
        delete x;
        method_thread_child();
        (o->*m)(a1, a2, a3, a4);
        return 0;
      }
    };
    XXX *x = new XXX;
    x->o = o;
    x->m = m;
    x->a1 = a1;
    x->a2 = a2;
    x->a3 = a3;
    x->a4 = a4;
    return method_thread_parent(&XXX::yyy, (void *) x, detach);
  }
  
  #endif
  