Common Lispでは、外部リソース(ソケット、ファイルシステムハンドルなど)を管理するための好ましい方法は何ですか?
CommonLispでシンプルなopengl2dプラットフォーマーを作ろうとしています。問題は、OpenGLテクスチャを追跡する方法がよくわからないことです(glDeleteTextures
不要になったときに削除する必要があります)。
C ++では、次のスキームを使用することを好みました。
- テクスチャクラスを作成する
- そのテクスチャクラスのスマート/ウィークポインタを作成します
- テクスチャを、ファイル名をテクスチャへの弱いポインタにマップするマップ(辞書/ハッシュテーブル)に格納します。
- 新しいテクスチャが要求されたら、マップを調べて、null以外(nil)の弱いポインタが使用可能かどうかを確認します。使用可能な場合は既存のオブジェクトを返し、そうでない場合は新しいテクスチャをロードします。
ただし、このスキームをCommon 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 ++の概念説明: スマートポインターとは何ですか?いつ使用する必要がありますか?