threading icon indicating copy to clipboard operation
threading copied to clipboard

Adding RwLock inplace initialization

Open darkestpigeon opened this issue 1 year ago • 8 comments

Right now an object with an RwLock field can't be properly initialized (myobj.rwLock = createRwLock() fails due to a deleted move constructor). This PR addresses this by introducing an in-place initializer (init(myobj.rwLock)).

darkestpigeon avatar Oct 17 '24 12:10 darkestpigeon

No, instead myobj.rwLock = createRwLock() should compile and treated as a move. The RwLock type needs to be marked with byref for this to work.

Araq avatar Oct 17 '24 13:10 Araq

@Araq checked out byref in the manual, but am still puzzled how this will work in this case. I have some structure that is shared by multiple threads, and is effectively passed around via a pointer. The structure shouldn't be moved around for the pointer to remain valid. The lock is part of this structure, and must be created in-place or moved in. It can't be moved in since the move constructor is deleted. How does byref help?

darkestpigeon avatar Oct 17 '24 13:10 darkestpigeon

Related: https://github.com/nim-lang/threading/issues/75

planetis-m avatar Oct 17 '24 14:10 planetis-m

Checked out the discussion in #75. Still don't understand how byref is relevant. I need RwLock to occupy a specific chunk of memory. How will byref help with this?

darkestpigeon avatar Oct 17 '24 14:10 darkestpigeon

By the way, perhaps the compiler could be patched so that in constructions like

var x: T
x = fn()

or

obj.x = fn()

the special result variable would reuse the already allocated var x or obj.x instead of making a new allocation on the stack. This would remove the need for an in-place constructor for types with deleted copy and sink. This could be problematic for stuff like x = fn(x), but for types with copy and sink deleted this doesn't make much sense anyway.

darkestpigeon avatar Oct 17 '24 15:10 darkestpigeon

the special result variable would reuse the already allocated var x or obj.x instead of making a new allocation on the stack.

That is what I mean with .byref, yes.

Araq avatar Oct 17 '24 18:10 Araq

No, instead myobj.rwLock = createRwLock() should compile and treated as a move. The RwLock type needs to be marked with byref for this to work.

I have a following toy example

type MyObj {.byref.} = object
  value: int

proc `=copy`(a: var MyObj, b: MyObj) {.error.}
proc `=sink`(a: var MyObj, b: MyObj) {.error.}

proc createMyObj(value: int): MyObj =
  result.value = value

var x: MyObj
x = createMyObj(3)

This doesn't compile ('=sink' is not available for type <MyObj>).

Nim Compiler Version 2.2.0 [Linux: amd64]
Compiled at 2024-10-02
Copyright (c) 2006-2024 by Andreas Rumpf

git hash: 78983f1876726a49c69d65629ab433ea1310ece1
active boot switches: -d:release

@Araq what am I doing wrong here?

darkestpigeon avatar Oct 18 '24 14:10 darkestpigeon

@Araq what am I doing wrong here?

We need to teach the compiler new tricks first. :-)

Araq avatar Oct 18 '24 14:10 Araq