在常见的Lisp中,管理外部资源(套接字,文件系统句柄等)的首选方法是什么?
我正在尝试用通用Lisp创建一个简单的opengl 2d平台程序。
问题是我不太确定如何跟踪OpenGL纹理(不再需要它们时,必须使用glDeleteTextures
删除它们)。
在C++中,我更喜欢使用以下方案:
但是,我不太确定如何将此方案移植到通用Lisp,因为:
(with-*
管理资源的首选方法似乎不合适,因为可以在函数调用的中间共享和加载/卸载资源。 据我所知,有几种可用的方法:
(defclass destructible () ())
(defmethod destroy ((obj destructible)) (print (format nil "destroy: ~A" obj)))
(defparameter *destructible-classes-list* nil)
(defmethod initialize-instance :after ((obj destructible) &key)
(progn
(push *destructible-classes-list* obj)
(print (format nil "init-instance: ~A" obj))))
(defmacro with-cleanup (&rest body)
`(let ((*destructible-classes-list* nil))
(progn ,@body (mapcar (lambda (x) (destroy x)) *destructible-classes-list*))))
(defclass refdata (destructible)
((value :accessor refdata-value :initform nil)
(ref :accessor refdata-ref :initform 0)
(weakrefcount :accessor refdata-weakref :initform 0)))
(defmethod incref ((ref refdata))
(if ref (incf (refdata-ref ref))))
(defmethod decref ((ref refdata))
(if ref
(progn (decf (refdata-ref ref))
(if (<= (refdata-ref ref) 0)
(progn (destroy (refdata-value ref))
(setf (refdata-value ref) nil))))))
(defmethod incweakref ((ref refdata))
(if ref (incf (refdata-weakref ref))))
(defmethod decweakref ((ref refdata))
(if ref (decf (refdata-weakref ref))))
(defclass refbase (destructible) ((data :accessor refbase-data :initform nil)))
(defmethod deref ((ref refbase))
(if (and (refbase-data ref) (refdata-value (refbase-data ref)))
(refdata-value (refbase-data ref))
nil))
(defclass strongref (refbase) ())
(defclass weakref (refbase) ())
(defmethod destroy :before ((obj strongref))
(decref (refbase-data obj)))
(defmethod destroy :before ((obj weakref))
(decweakref (refbase-data obj)))
(defmethod initialize-instance :after ((obj strongref) &key)
(incref (refbase-data obj)))
(defmethod initialize-instance :after ((obj weakref) &key)
(incweakref (refbase-data obj)))
有更好的方法吗?
C++概念说明: What is a smart pointer and when should I use one?
最佳答案
如果要处理动态范围范围,请使用UNWIND-PROTECT。如果程序离开该范围(通常或发生错误),则将调用清理表单。只是在那儿分配或做任何你想做的事。
有时Lisps使用某种“资源”机制来跟踪已使用和未使用的对象。这样的库提供了从池中的快速分配,资源对象的分配,初始化,释放,映射。 CLIM定义了原始版本:Resources。 CCL具有类似的原始版本。
在带有“计时器”的Lisp中,您可以定期运行一个函数来查找要释放的“对象”。在CCL中,您可以使用PROCESS-WAIT
使用一个可以休眠一定时间的线程。
关于您的编码风格的一点:
FORMAT
可以直接输出到流,无需PRINT (defmethod foo ((e bar)) (if e ...))
:IF
没有意义。 e
将始终是一个对象。 PROGN
。如果需要,可以将IF
替换为WHEN
时将其删除。 关于opengl - 管理外部资源(类似于C++中的RAII?),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13322823/