--- /dev/null
+#ifndef __COCO_IR_USE_HOOK_H__
+#define __COCO_IR_USE_HOOK_H__
+
+#include "coco/IR/Object.h"
+#include "coco/IR/ObjectInfo.forward.h"
+
+#include "coco/ADT/PtrLink.h"
+
+namespace coco
+{
+
+class UseHook final
+{
+public:
+ UseHook(const PtrLink<Object, ObjectInfo> *obj_link, Object::Use *use)
+ : _obj_link{obj_link}, _use{use}
+ {
+ // DO NOTHING
+ }
+
+private:
+ ObjectInfo *info(Object *o) const;
+
+public:
+ void onTake(Object *o);
+ void onRelease(Object *o);
+
+private:
+ const PtrLink<Object, ObjectInfo> *const _obj_link;
+ Object::Use *const _use;
+};
+
+} // namespace coco
+
+#endif // __COCO_IR_USE_HOOK_H__
--- /dev/null
+#include "coco/IR/UseHook.h"
+#include "coco/IR/ObjectInfo.h"
+
+#include <cassert>
+
+namespace coco
+{
+
+ObjectInfo *UseHook::info(Object *o) const
+{
+ auto info = _obj_link->find(o);
+ assert(info != nullptr);
+ return info;
+}
+
+void UseHook::onTake(Object *o) { info(o)->user()->insert(_use); }
+void UseHook::onRelease(Object *o) { info(o)->user()->erase(_use); }
+
+} // namespace coco
--- /dev/null
+#include "coco/IR/UseHook.h"
+#include "coco/IR/ObjectInfo.h"
+#include "coco/IR/ObjectManager.h"
+
+#include "coco/IR/FeatureObject.h"
+
+#include <gtest/gtest.h>
+
+namespace
+{
+namespace mock
+{
+struct Use final : public coco::Object::Use
+{
+};
+} // namespace mock
+} // namespace
+
+namespace
+{
+class UseHookTest : public ::testing::Test
+{
+protected:
+ coco::PtrLink<coco::Bag, coco::BagInfo> bag_link;
+ coco::PtrLink<coco::Object, coco::ObjectInfo> obj_link;
+
+ coco::ObjectManager obj_mgr{&obj_link, &bag_link};
+};
+} // namespace
+
+TEST_F(UseHookTest, TakeAndRelease)
+{
+ auto o = obj_mgr.create(nncc::core::ADT::feature::Shape{1, 1, 1});
+
+ ::mock::Use use;
+
+ coco::UseHook hook{&obj_link, &use};
+
+ hook.onTake(o);
+ hook.onRelease(o);
+}