opengl - 管理外部资源(类似于C++中的RAII?)

标签 opengl common-lisp

在常见的Lisp中,管理外部资源(套接字,文件系统句柄等)的首选方法是什么?

我正在尝试用通用Lisp创建一个简单的opengl 2d平台程序。
问题是我不太确定如何跟踪OpenGL纹理(不再需要它们时,必须使用glDeleteTextures删除它们)。

在C++中,我更喜欢使用以下方案:

  • 使纹理类
  • 为该纹理类
  • 创建智能/弱指针
  • 将纹理存储在映射(字典/哈希表)中,该映射将文件名映射到指向纹理的弱指针。
  • 当请求新的纹理时,请查看 map ,看看是否有可用的非空(nil)弱指针。如果可用,则返回现有对象,否则加载新纹理。

  • 但是,我不太确定如何将此方案移植到通用Lisp,因为:
  • 没有析构函数。
  • 有垃圾收集器,看来我的实现(Windows平台上的clozureCL)支持终结器,但据我所知,不建议在通用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++概念说明: 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/

    相关文章:

    c - 纹理似乎正在读取未初始化的内存

    c++ - 当顶点属性大小不匹配时会发生什么

    haskell - 四元数旋转有一个奇怪的行为(Haskell OpenGL)

    common-lisp - Lisp 网络故事 : How to fix the blogdemo example (Chapter 4)?

    lisp - 为什么 Lisp 中的 consing 很慢?

    c++ - 着色器纹理值与创建纹理时写入的值不同

    c++ - 有没有办法在下一个命令之前等待 GPU 的最后一个命令?

    lisp - 关于 Prolog 的实现

    python - 需要帮助让 CLisp 将标准输入读入列表

    lisp - Common Lisp 函数打开列表以显示列表中元素的顺序?