keep_alive call policy (analogous to Boost.Python's with_custodian_and_ward, fixes #62)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index b1fcb9b..ebb4ea6 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -109,6 +109,7 @@
   example/example10.cpp
   example/example11.cpp
   example/example12.cpp
+  example/example13.cpp
 )
 
 # Don't add a 'lib' prefix to the shared library
@@ -179,7 +180,7 @@
 
 enable_testing()
 set(RUN_TEST ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/example/run_test.py)
-foreach(i RANGE 1 12)
+foreach(i RANGE 1 13)
   add_test(NAME example${i} COMMAND ${RUN_TEST} example${i})
 endforeach()
 
diff --git a/docs/advanced.rst b/docs/advanced.rst
index 43a3b1a..84ca73c 100644
--- a/docs/advanced.rst
+++ b/docs/advanced.rst
@@ -446,6 +446,33 @@
         return m.ptr();
     }
 
+
+Additional call policies
+========================
+
+In addition to the above return value policies, further `call policies` can be
+specified to indicate dependencies between parameters. There is currently just
+one policy named ``keep_alive<Nurse, Patient>``, which indicates that the
+argument with index ``Patient`` should be kept alive at least until the
+argument with index ``Nurse`` is freed by the garbage collector; argument
+indices start at one, while zero refers to the return value. Arbitrarily many
+call policies can be specified.
+
+For instance, binding code for a a list append operation that ties the lifetime
+of the newly added element to the underlying container might be declared as
+follows:
+
+.. code-block:: cpp
+
+    py::class_<List>(m, "List")
+        .def("append", &List::append, py::keep_alive<1, 2>());
+
+.. note::
+
+    ``keep_alive`` is analogous to the ``with_custodian_and_ward`` (if Nurse,
+    Patient != 0) and ``with_custodian_and_ward_postcall`` (if Nurse/Patient ==
+    0) policies from Boost.Python.
+
 Implicit type conversions
 =========================
 
diff --git a/example/example.cpp b/example/example.cpp
index 0b97359..d130551 100644
--- a/example/example.cpp
+++ b/example/example.cpp
@@ -21,6 +21,7 @@
 void init_ex10(py::module &);
 void init_ex11(py::module &);
 void init_ex12(py::module &);
+void init_ex13(py::module &);
 
 PYBIND11_PLUGIN(example) {
     py::module m("example", "pybind example plugin");
@@ -37,6 +38,7 @@
     init_ex10(m);
     init_ex11(m);
     init_ex12(m);
+    init_ex13(m);
 
     return m.ptr();
 }
diff --git a/example/example13.cpp b/example/example13.cpp
new file mode 100644
index 0000000..782db31
--- /dev/null
+++ b/example/example13.cpp
@@ -0,0 +1,37 @@
+/*
+    example/example13.cpp -- keep_alive modifier (pybind11's version
+    of Boost.Python's with_custodian_and_ward / with_custodian_and_ward_postcall)
+
+    Copyright (c) 2015 Wenzel Jakob <wenzel@inf.ethz.ch>
+
+    All rights reserved. Use of this source code is governed by a
+    BSD-style license that can be found in the LICENSE file.
+*/
+
+#include "example.h"
+
+class Child {
+public:
+    Child() { std::cout << "Allocating child." << std::endl; }
+    ~Child() { std::cout << "Releasing child." << std::endl; }
+};
+
+class Parent {
+public:
+    Parent() { std::cout << "Allocating parent." << std::endl; }
+    ~Parent() { std::cout << "Releasing parent." << std::endl; }
+    void addChild(Child *) { }
+    Child *returnChild() { return new Child(); }
+};
+
+void init_ex13(py::module &m) {
+    py::class_<Parent>(m, "Parent")
+        .def(py::init<>())
+        .def("addChild", &Parent::addChild)
+        .def("addChildKeepAlive", &Parent::addChild, py::keep_alive<1, 2>())
+        .def("returnChild", &Parent::returnChild)
+        .def("returnChildKeepAlive", &Parent::returnChild, py::keep_alive<1, 0>());
+
+    py::class_<Child>(m, "Child")
+        .def(py::init<>());
+}
diff --git a/example/example13.py b/example/example13.py
new file mode 100644
index 0000000..ad0176e
--- /dev/null
+++ b/example/example13.py
@@ -0,0 +1,46 @@
+from __future__ import print_function
+import sys
+import gc
+sys.path.append('.')
+
+from example import Parent, Child
+
+if True:
+    p = Parent()
+    p.addChild(Child())
+    gc.collect()
+    print(p)
+    p = None
+
+gc.collect()
+print("")
+
+if True:
+    p = Parent()
+    p.returnChild()
+    gc.collect()
+    print(p)
+    p = None
+
+gc.collect()
+print("")
+
+if True:
+    p = Parent()
+    p.addChildKeepAlive(Child())
+    gc.collect()
+    print(p)
+    p = None
+gc.collect()
+print("")
+
+if True:
+    p = Parent()
+    p.returnChildKeepAlive()
+    gc.collect()
+    print(p)
+    p = None
+
+gc.collect()
+print("")
+print("Terminating..")
diff --git a/example/example13.ref b/example/example13.ref
new file mode 100644
index 0000000..7eb02c5
--- /dev/null
+++ b/example/example13.ref
@@ -0,0 +1,25 @@
+Allocating parent.
+Allocating child.
+Releasing child.
+<example.Parent object at 0x10eb726c0>
+Releasing parent.
+
+Allocating parent.
+Allocating child.
+Releasing child.
+<example.Parent object at 0x10eb726c0>
+Releasing parent.
+
+Allocating parent.
+Allocating child.
+<example.Parent object at 0x10eb726c0>
+Releasing parent.
+Releasing child.
+
+Allocating parent.
+Allocating child.
+<example.Parent object at 0x10eb726c0>
+Releasing parent.
+Releasing child.
+
+Terminating..
diff --git a/include/pybind11/common.h b/include/pybind11/common.h
index 8b34e4e..a2a4498 100644
--- a/include/pybind11/common.h
+++ b/include/pybind11/common.h
@@ -167,6 +167,7 @@
     PyObject_HEAD
     type *value;
     PyObject *parent;
+    PyObject *weakrefs;
     bool owned : 1;
     bool constructed : 1;
     holder_type holder;
diff --git a/include/pybind11/pybind11.h b/include/pybind11/pybind11.h
index 19a4655..e8b385c 100644
--- a/include/pybind11/pybind11.h
+++ b/include/pybind11/pybind11.h
@@ -58,6 +58,28 @@
 /// Annotation for function siblings
 struct sibling { PyObject *value; sibling(handle value) : value(value.ptr()) { } };
 
+/// Keep patient alive while nurse lives
+template <int Nurse, int Patient> struct keep_alive { };
+
+NAMESPACE_BEGIN(detail)
+template <typename... Args> struct process_dynamic;
+template <typename T> struct process_dynamic<T> {
+    static void precall(PyObject *) { }
+    static void postcall(PyObject *, PyObject *) { }
+};
+template <> struct process_dynamic<> : public process_dynamic<void> { };
+template <typename T, typename... Args> struct process_dynamic<T, Args...> {
+    static void precall(PyObject *arg) {
+        process_dynamic<T>::precall(arg);
+        process_dynamic<Args...>::precall(arg);
+    }
+    static void postcall(PyObject *arg, PyObject *ret) {
+        process_dynamic<T>::postcall(arg, ret);
+        process_dynamic<Args...>::postcall(arg, ret);
+    }
+};
+NAMESPACE_END(detail)
+
 /// Wraps an arbitrary C++ function/method/lambda function/.. into a callable Python object
 class cpp_function : public function {
 private:
@@ -110,6 +132,8 @@
         (void) unused;
     }
 
+    template <int Nurse, int Patient>
+    static void process_extra(const keep_alive<Nurse, Patient> &, function_entry *) { }
     static void process_extra(const char *doc, function_entry *entry) { entry->doc = (char *) doc; }
     static void process_extra(const pybind11::doc &d, function_entry *entry) { entry->doc = (char *) d.value; }
     static void process_extra(const pybind11::name &n, function_entry *entry) { entry->name = (char *) n.value; }
@@ -154,7 +178,10 @@
             cast_in args;
             if (!args.load(pyArgs, true))
                 return (PyObject *) 1; /* Special return code: try next overload */
-            return cast_out::cast(args.template call<Return>((Return (*)(Args...)) entry->data), entry->policy, parent);
+            detail::process_dynamic<Extra...>::precall(pyArgs);
+            PyObject *result = cast_out::cast(args.template call<Return>((Return (*)(Args...)) entry->data), entry->policy, parent);
+            detail::process_dynamic<Extra...>::postcall(pyArgs, result);
+            return result;
         };
 
         process_extras(std::make_tuple(std::forward<Extra>(extra)...), m_entry);
@@ -210,7 +237,10 @@
             cast_in args;
             if (!args.load(pyArgs, true))
                 return (PyObject *) 1; /* Special return code: try next overload */
-            return cast_out::cast(args.template call<Return>(((capture *) entry->data)->f), entry->policy, parent);
+            detail::process_dynamic<Extra...>::precall(pyArgs);
+            PyObject *result = cast_out::cast(args.template call<Return>(((capture *) entry->data)->f), entry->policy, parent);
+            detail::process_dynamic<Extra...>::postcall(pyArgs, result);
+            return result;
         };
 
         process_extras(std::make_tuple(std::forward<Extra>(extra)...), m_entry);
@@ -568,8 +598,10 @@
         type->ht_type.tp_as_sequence = &type->as_sequence;
         type->ht_type.tp_as_mapping = &type->as_mapping;
         type->ht_type.tp_base = (PyTypeObject *) parent;
+        type->ht_type.tp_weaklistoffset = offsetof(instance<void>, weakrefs);
+
         if (doc) {
-            size_t size = strlen(doc)+1;
+            size_t size = strlen(doc) + 1;
             type->ht_type.tp_doc = (char *) PyObject_MALLOC(size);
             memcpy((void *) type->ht_type.tp_doc, doc, size);
         }
@@ -654,6 +686,8 @@
                 registered_instances.erase(it);
             }
             Py_XDECREF(self->parent);
+            if (self->weakrefs)
+                PyObject_ClearWeakRefs((PyObject *) self);
         }
         Py_TYPE(self)->tp_free((PyObject*) self);
     }
@@ -927,6 +961,37 @@
         class_.def("__init__", [](Base *instance, Args... args) { new (instance) Base(args...); }, std::forward<Extra>(extra)...);
     }
 };
+
+PYBIND11_NOINLINE inline void keep_alive_impl(int Nurse, int Patient, PyObject *arg, PyObject *ret) {
+    /* Clever approach based on weak references taken from Boost.Python */
+    PyObject *nurse   =   Nurse > 0 ? PyTuple_GetItem(arg, Nurse - 1)   : ret;
+    PyObject *patient = Patient > 0 ? PyTuple_GetItem(arg, Patient - 1) : ret;
+
+    if (nurse == nullptr || patient == nullptr)
+        throw std::runtime_error("Could not activate keep_alive");
+
+    cpp_function disable_lifesupport(
+        [patient](handle weakref) { Py_DECREF(patient); weakref.dec_ref(); }
+   );
+
+    PyObject *weakref = PyWeakref_NewRef(nurse, disable_lifesupport.ptr());
+    if (weakref == nullptr)
+        throw std::runtime_error("Could not allocate weak reference!");
+
+    Py_INCREF(patient); /* reference patient and leak the weak reference */
+}
+
+template <int Nurse, int Patient> struct process_dynamic<keep_alive<Nurse, Patient>> : public process_dynamic<void> {
+    template <int N = Nurse, int P = Patient, typename std::enable_if<N != 0 && P != 0, int>::type = 0>
+    static void precall(PyObject *arg) { keep_alive_impl(Nurse, Patient, arg, nullptr); }
+    template <int N = Nurse, int P = Patient, typename std::enable_if<N != 0 && P != 0, int>::type = 0>
+    static void postcall(PyObject *, PyObject *) { }
+    template <int N = Nurse, int P = Patient, typename std::enable_if<N == 0 || P == 0, int>::type = 0>
+    static void precall(PyObject *) { }
+    template <int N = Nurse, int P = Patient, typename std::enable_if<N == 0 || P == 0, int>::type = 0>
+    static void postcall(PyObject *arg, PyObject *ret) { keep_alive_impl(Nurse, Patient, arg, ret); }
+};
+
 NAMESPACE_END(detail)
 
 template <typename... Args> detail::init<Args...> init() { return detail::init<Args...>(); };