Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove destructors #18

Merged
merged 1 commit into from
Dec 7, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 2 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,13 @@ nim-csfml
Warning
-------

This library consists of class wrappers implemented as `ptr object`. Because Nim does not allow attaching pointers to the garbage collector, I decided to use [destructors][nim-destructors] hoping that would be a reasonable way to implement automatic disposal of objects. However, this feature is based on lexical scoping, which (as I later realized) makes things problematic: the disposal behavior is more like normal `object`s rather than `ref objects`, and sometimes unpredictable.

It is recommended to disable destructors (pass `-d:csfmlNoDestructors` to the compiler) and dispose of the `ptr object`s manually by calling `destroy`. Standard memory management caveats apply: destroying objects that are still used will break things, forgetting to destroy is a memory leak.

There is no good way to fix this under the current state of the language, short of reimplementing everything with additional wrapper classes which also add a lot of overhead.
This library consists of class wrappers implemented as `ptr object`. Because Nim does not allow attaching pointers to the garbage collector, disposal of objects is not implemented and needs to be manual, by calling the `destroy` methods. Standard memory management caveats apply: destroying objects that are still used will break things, forgetting to destroy is a memory leak.

[More details](https://github.com/BlaXpirit/nim-csfml/issues/6)

This library is not under active development, but detailed bug reports will be given proper attention.




Introduction
------------

Expand All @@ -29,7 +23,7 @@ The API attempts to be very similar to SFML's, but some general changes are pres

- To construct an object (`sf::SomeType x(param)`), use a corresponding procedure (there are 2 variations):
- `var x = newSomeType(param)`, which means it is a `ptr object`.
- Such objects have [destructors][nim-destructors] associated with them (no need to call `destroy` manually).
- Such objects need to have `destroy` called to properly dispose of them.
- Never create them using `new`.
- `var x = someType(param)`, which means it is an `object` (in CSFML it corresponds to a simple `struct`).
- `Vector2(i|f)`, `Vector3f` and `(Int|Float)Rect` should be created using special `vec2`, `vec3` and `rect` procs.
Expand Down Expand Up @@ -102,7 +96,6 @@ This library uses and is based on [SFML][] and [CSFML][].
[csfml]: http://www.sfml-dev.org/download/csfml/
[sfml-tutorials]: http://www.sfml-dev.org/tutorials/
[nim]: http://nim-lang.org/
[nim-destructors]: http://nim-lang.org/docs/manual.html#type-bound-operations-destructors
[python]: http://python.org/
[nimble]: https://github.com/nim-lang/nimble
[nimrod-sfml]: https://github.com/fowlmouth/nimrod-sfml
4 changes: 4 additions & 0 deletions examples/flippy_bird.nim
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,7 @@ while window.open:
window.draw bird

window.display()

bird.destroy()
bird_texture.destroy()
window.destroy()
4 changes: 3 additions & 1 deletion examples/gl.nim
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,6 @@ while window.open:
glColor3f(0.0, 0.5, 1.0); glVertex2f( 0.0, -1.0)
glEnd()

window.display()
window.display()

window.destroy()
11 changes: 11 additions & 0 deletions examples/pong.nim
Original file line number Diff line number Diff line change
Expand Up @@ -178,3 +178,14 @@ while window.open:

# Display things on screen
window.display()

clock.destroy()
AITimer.destroy()
pauseMessage.destroy()
font.destroy()
ball.destroy()
rightPaddle.destroy()
leftPaddle.destroy()
ballSound.destroy()
ballSoundBuffer.destroy()
window.destroy()
9 changes: 9 additions & 0 deletions examples/shader.nim
Original file line number Diff line number Diff line change
Expand Up @@ -59,3 +59,12 @@ while window.open:
window.draw text, renderStates(shader=wbShader)

window.display()

clock.destroy()
window.destroy()
wbShader.destroy()
text.destroy()
font.destroy()
pxShader.destroy()
sprite.destroy()
texture.destroy()
5 changes: 5 additions & 0 deletions examples/shapes.nim
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ while window.open:
vertexArray.append vertex(vec2(100, 0), Red)
vertexArray.append vertex(vec2(0, 100), Blue)
window.draw vertexArray
vertexArray.destroy()

# Top right
var vertexSeq = @[
Expand All @@ -38,6 +39,7 @@ while window.open:
convexShape[2] = vec2(0, 100)
convexShape.fillColor = Green
window.draw convexShape
convexShape.destroy()

# Bottom right
proc getPointCount(p: pointer): int {.cdecl.} = 3
Expand All @@ -50,5 +52,8 @@ while window.open:
customShape.update()
customShape.fillColor = Green
window.draw customShape
customShape.destroy()

window.display()

window.destroy()
2 changes: 2 additions & 0 deletions examples/simple.nim
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,5 @@ while window.open:
if event.kind == EventType.Closed:
window.close()
window.display()

window.destroy()
6 changes: 6 additions & 0 deletions examples/snakes.nim
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ proc draw[T](self: Food, target: T, states: RenderStates) =
circle.position = vec2(self.position)+vec2(0.05, 0.05)
circle.fill_color = self.color
target.draw circle, states
circle.destroy()



Expand Down Expand Up @@ -107,6 +108,7 @@ proc draw[T](self: Snake, target: T, states: RenderStates) =
segment.position = vec2(current)+vec2(0.05, 0.05)
segment.fill_color = self.color
target.draw segment, states
segment.destroy()

# The following is eye candy and may be removed
# but change the above to RectangleShape of size (0.9, 0.9)
Expand All @@ -124,6 +126,7 @@ proc draw[T](self: Snake, target: T, states: RenderStates) =
connection.position = vec2(current)+vec2(float(d.x)/2.0+0.05, float(d.y)/2.0+0.05)
connection.fill_color = self.color
target.draw connection, states
connection.destroy()

# Draw eyes with a darkened color
var eye = new_CircleShape(radius=0.2/2)
Expand All @@ -136,6 +139,7 @@ proc draw[T](self: Snake, target: T, states: RenderStates) =
eye.position = self.body[0]+vec2(0.4, 0.4)-delta
target.draw eye, states

eye.destroy()


proc new_Field(size: Vector2i): Field =
Expand Down Expand Up @@ -222,3 +226,5 @@ while window.open:
window.draw field, states

window.display()

window.destroy()
2 changes: 2 additions & 0 deletions examples/sound_capture.nim
Original file line number Diff line number Diff line change
Expand Up @@ -41,5 +41,7 @@ else:
while sound.status == SoundStatus.Playing:
echo "Playing... ", sound.playingOffset.asSeconds, " sec"
sleep 100.milliseconds
sound.destroy()

recorder.destroy()
echo "Done!"
3 changes: 2 additions & 1 deletion examples/test_graphics.nim
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,5 @@ block:
let s = "Випробування"
var txt = newText()
txt.str = s
assert txt.str == s
assert txt.str == s
txt.destroy()
1 change: 1 addition & 0 deletions examples/test_system.nim
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,4 @@ block:
assert t2 > 50000
assert t2 < 150000

clock.destroy()
4 changes: 4 additions & 0 deletions examples/typing.nim
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,7 @@ while window.open:
window.clear White
window.draw text
window.display()

text.destroy()
font.destroy()
window.destroy()
2 changes: 0 additions & 2 deletions generate/generate.py
Original file line number Diff line number Diff line change
Expand Up @@ -188,8 +188,6 @@ def handle_function(main, params):
main_sgn = 'proc {nfname}{public}({sparams}): {nftype}'
main_fn = '{nfname}'
pragmas = []
if nfname=='destroy':
pragmas.append('destroy')
if nfname.startswith('get') and nfname[3].isupper() and len(params)==1:
nfname = nfname[3].lower()+nfname[4:]
elif nfname.startswith('is') and nfname[2].isupper() and len(params)==1:
Expand Down
12 changes: 6 additions & 6 deletions src/csfml/private/audio_gen.nim
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ proc newMusic*(stream: var InputStream): Music {.
## *Returns:* A new Music object (NULL if failed)

proc destroy*(music: Music) {.
destroy, cdecl, importc: "sfMusic_destroy".}
cdecl, importc: "sfMusic_destroy".}
## Destroy a music
##
## *Arguments*:
Expand Down Expand Up @@ -427,7 +427,7 @@ proc copy*(sound: Sound): Sound {.
## *Returns:* A new Sound object which is a copy of ``sound``

proc destroy*(sound: Sound) {.
destroy, cdecl, importc: "sfSound_destroy".}
cdecl, importc: "sfSound_destroy".}
## Destroy a sound
##
## *Arguments*:
Expand Down Expand Up @@ -745,7 +745,7 @@ proc copy*(soundBuffer: SoundBuffer): SoundBuffer {.
## *Returns:* A new SoundBuffer object which is a copy of ``soundBuffer``

proc destroy*(soundBuffer: SoundBuffer) {.
destroy, cdecl, importc: "sfSoundBuffer_destroy".}
cdecl, importc: "sfSoundBuffer_destroy".}
## Destroy a sound buffer
##
## *Arguments*:
Expand Down Expand Up @@ -834,7 +834,7 @@ proc newSoundBufferRecorder*(): SoundBufferRecorder {.
## *Returns:* A new SoundBufferRecorder object (NULL if failed)

proc destroy*(soundBufferRecorder: SoundBufferRecorder) {.
destroy, cdecl, importc: "sfSoundBufferRecorder_destroy".}
cdecl, importc: "sfSoundBufferRecorder_destroy".}
## Destroy a sound buffer recorder
##
## *Arguments*:
Expand Down Expand Up @@ -911,7 +911,7 @@ proc newSoundRecorder*(onStart: SoundRecorderStartCallback, onProcess: SoundReco
## *Returns:* A new SoundRecorder object (NULL if failed)

proc destroy*(soundRecorder: SoundRecorder) {.
destroy, cdecl, importc: "sfSoundRecorder_destroy".}
cdecl, importc: "sfSoundRecorder_destroy".}
## Destroy a sound recorder
##
## *Arguments*:
Expand Down Expand Up @@ -1054,7 +1054,7 @@ proc newSoundStream*(onGetData: SoundStreamGetDataCallback, onSeek: SoundStreamS
## *Returns:* A new SoundStream object

proc destroy*(soundStream: SoundStream) {.
destroy, cdecl, importc: "sfSoundStream_destroy".}
cdecl, importc: "sfSoundStream_destroy".}
## Destroy a sound stream
##
## *Arguments*:
Expand Down
6 changes: 0 additions & 6 deletions src/csfml/private/common.nim
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,6 @@

{.deadCodeElim: on.}

when defined(csfmlNoDestructors):
{.pragma: destroy.}
else:
{.experimental.}
{.pragma: destroy, override.}


when defined(windows):
const lib = "csfml-" & module & "-2.dll"
Expand Down
30 changes: 15 additions & 15 deletions src/csfml/private/graphics_gen.nim
Original file line number Diff line number Diff line change
Expand Up @@ -375,7 +375,7 @@ proc copy*(shape: CircleShape): CircleShape {.
## *Returns:* Copied object

proc destroy*(shape: CircleShape) {.
destroy, cdecl, importc: "sfCircleShape_destroy".}
cdecl, importc: "sfCircleShape_destroy".}
## Destroy an existing circle Shape
##
## *Arguments*:
Expand Down Expand Up @@ -735,7 +735,7 @@ proc copy*(shape: ConvexShape): ConvexShape {.
## *Returns:* Copied object

proc destroy*(shape: ConvexShape) {.
destroy, cdecl, importc: "sfConvexShape_destroy".}
cdecl, importc: "sfConvexShape_destroy".}
## Destroy an existing convex Shape
##
## *Arguments*:
Expand Down Expand Up @@ -1132,7 +1132,7 @@ proc copy*(font: Font): Font {.
## *Returns:* Copied object

proc destroy*(font: Font) {.
destroy, cdecl, importc: "sfFont_destroy".}
cdecl, importc: "sfFont_destroy".}
## Destroy an existing font
##
## *Arguments*:
Expand Down Expand Up @@ -1315,7 +1315,7 @@ proc copy*(image: Image): Image {.
## *Returns:* Copied object

proc destroy*(image: Image) {.
destroy, cdecl, importc: "sfImage_destroy".}
cdecl, importc: "sfImage_destroy".}
## Destroy an existing image
##
## *Arguments*:
Expand Down Expand Up @@ -1468,7 +1468,7 @@ proc copy*(shape: RectangleShape): RectangleShape {.
## *Returns:* Copied object

proc destroy*(shape: RectangleShape) {.
destroy, cdecl, importc: "sfRectangleShape_destroy".}
cdecl, importc: "sfRectangleShape_destroy".}
## Destroy an existing rectangle shape
##
## *Arguments*:
Expand Down Expand Up @@ -1834,7 +1834,7 @@ proc newRenderTexture*(width: cint, height: cint, depthBuffer: BoolInt): RenderT
## *Returns:* A new RenderTexture object, or NULL if it failed

proc destroy*(renderTexture: RenderTexture) {.
destroy, cdecl, importc: "sfRenderTexture_destroy".}
cdecl, importc: "sfRenderTexture_destroy".}
## Destroy an existing render texture
##
## *Arguments*:
Expand Down Expand Up @@ -2152,7 +2152,7 @@ proc newRenderWindow*(handle: WindowHandle, settings: ContextSettings): RenderWi
newRenderWindow(handle, Csettings)

proc destroy*(renderWindow: RenderWindow) {.
destroy, cdecl, importc: "sfRenderWindow_destroy".}
cdecl, importc: "sfRenderWindow_destroy".}
## Destroy an existing render window
##
## *Arguments*:
Expand Down Expand Up @@ -2677,7 +2677,7 @@ proc newShader*(vertexShaderStream: var InputStream, fragmentShaderStream: var I
## *Returns:* A new Shader object, or NULL if it failed

proc destroy*(shader: Shader) {.
destroy, cdecl, importc: "sfShader_destroy".}
cdecl, importc: "sfShader_destroy".}
## Destroy an existing shader
##
## *Arguments*:
Expand Down Expand Up @@ -2896,7 +2896,7 @@ proc newShape*(getPointCount: ShapeGetPointCountCallback, getPoint: ShapeGetPoin
## *Returns:* A new Shape object

proc destroy*(shape: Shape) {.
destroy, cdecl, importc: "sfShape_destroy".}
cdecl, importc: "sfShape_destroy".}
## Destroy an existing shape
##
## *Arguments*:
Expand Down Expand Up @@ -3239,7 +3239,7 @@ proc copy*(sprite: Sprite): Sprite {.
## *Returns:* Copied object

proc destroy*(sprite: Sprite) {.
destroy, cdecl, importc: "sfSprite_destroy".}
cdecl, importc: "sfSprite_destroy".}
## Destroy an existing sprite
##
## *Arguments*:
Expand Down Expand Up @@ -3512,7 +3512,7 @@ proc copy*(text: Text): Text {.
## *Returns:* Copied object

proc destroy*(text: Text) {.
destroy, cdecl, importc: "sfText_destroy".}
cdecl, importc: "sfText_destroy".}
## Destroy an existing text
##
## *Arguments*:
Expand Down Expand Up @@ -3904,7 +3904,7 @@ proc copy*(texture: Texture): Texture {.
## *Returns:* Copied object

proc destroy*(texture: Texture) {.
destroy, cdecl, importc: "sfTexture_destroy".}
cdecl, importc: "sfTexture_destroy".}
## Destroy an existing texture
##
## *Arguments*:
Expand Down Expand Up @@ -4068,7 +4068,7 @@ proc copy*(transformable: Transformable): Transformable {.
## *Returns:* Copied object

proc destroy*(transformable: Transformable) {.
destroy, cdecl, importc: "sfTransformable_destroy".}
cdecl, importc: "sfTransformable_destroy".}
## Destroy an existing transformable
##
## *Arguments*:
Expand Down Expand Up @@ -4233,7 +4233,7 @@ proc copy*(vertexArray: VertexArray): VertexArray {.
## *Returns:* Copied object

proc destroy*(vertexArray: VertexArray) {.
destroy, cdecl, importc: "sfVertexArray_destroy".}
cdecl, importc: "sfVertexArray_destroy".}
## Destroy an existing vertex array
##
## *Arguments*:
Expand Down Expand Up @@ -4363,7 +4363,7 @@ proc copy*(view: View): View {.
## *Returns:* Copied object

proc destroy*(view: View) {.
destroy, cdecl, importc: "sfView_destroy".}
cdecl, importc: "sfView_destroy".}
## Destroy an existing view
##
## *Arguments*:
Expand Down
Loading