在 common lisp 中,管理外部资源(套接字、文件系统句柄等)的首选方法是什么?
我正在尝试用 common lisp 制作一个简单的 opengl 2d 平台游戏。问题是我不太确定如何跟踪 OpenGL 纹理(glDeleteTextures
在不再需要它们时必须删除)。
在 C++ 中,我更喜欢使用以下方案:
- 制作纹理类
- 为该纹理类制作智能/弱指针
- 将纹理存储在将文件名映射到指向纹理的弱指针的映射(字典/哈希表)中。
- 当请求新的纹理时,查看地图,看看是否有可用的非空 (nil) 弱指针。如果可用,则返回现有对象,否则加载新纹理。
但是,我不太确定如何将此方案移植到 common lisp,因为:
- 没有析构函数。
- 有垃圾收集器,而且我的实现(Windows 平台上的 clozureCL)似乎支持终结器,但据我所知,不建议在 common lisp 中使用终结器,因为它们不是确定性的。
- 使用管理资源的首选方式在
(with-*
那里看起来不合适,因为资源可以共享,并在函数调用中间加载/卸载。
据我所知,有几种方法可用:
- 放弃自动资源管理,手动进行。
使用宏实现类似于 C++ RAII、weakpointer 和 smartpointer 的东西(此代码可能不起作用):
(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++ 概念说明: 什么是智能指针,什么时候应该使用它?