I am having trouble with the below mentioned code.
It crashes in Xcode 9.0 beta 3 (9M174d) but doesn’t crash in Xcode 8.3.3 (8E3004b)
Observations in Xcode 9:
- When Car is changed into a struct and test is made to be mutating, it doesn’t crash
- When Helper is changed to class, it doesn’t crash
- In Helper, when doSomething is changed to be non-mutating, it doesn’t crash
Questions:
- Is there a bug in my code which is being detected in Xcode 9 ? If so could you please explain and suggest an alternate approach / fix ?
- Is this occurring because class doesn’t have the concept of mutating but struct does and passing one’s function into the other causes this ?
func f1() {
_ = helper.v1 //Crash - Simultaneous accesses to <memory address>, but modification requires exclusive access.
}
}
var car = Car()
car.test()
Crash:
Simultaneous accesses to <memory address1>, but modification requires exclusive access.
Previous access (a modification) started at SimultaneousAccess`Car.test() + 65 (<memory address2>).
Testing:
- Tested by creating macOS command line application and iOS application (Simulator)
- Is there a bug in my code which is being detected in Xcode 9 ?
Yes. The problem here is that `doSomething(f1:)` is a mutating function, so it acts like it takes an `inout` reference to `self.helper`. That’s one mutable reference. It then calls `Car.f1()`, which tries to get a non-mutating reference to exactly the same struct. This is outlawed in Swift 4 as part of the memory ownership effort.
You can read more about the specific change in SE-0176 “Enforce Exclusive Access to Memory”.
If so could you please explain and suggest an alternate approach / fix ?
It’s hard to offer concrete suggestions without knowing more about your high-level goals. One option is for `doSomething(f1:)` to pass the `inout` reference through to `f1`. For example:
but whether that makes sense in your code is for you to decide.
Share and Enjoy
···
On 24 Jul 2017, at 07:04, somu subscribe via swift-users <swift-users@swift.org> wrote:
--
Quinn "The Eskimo!" <http://www.apple.com/developer/>
Apple Developer Relations, Developer Technical Support, Core OS/Hardware
Thank a lot Quinn, your solution to use inout works well without crashing.
Question 1:
- Also changing Helper to a class doesn’t seem to crash. Is that a solution that wouldn’t cause a crash or just works by chance ?
Background:
Just a little background into what I was trying to achieve (I could be wrong):
- I have a set of classes C1, C2, C3 which has a lot of common code
- I would like to build something that can be reused without exposing the implementation details. (I can subclass but would expose the underlying functions, same applies to protocol as well)
- I thought I would build helper class / struct which would contain the common code. I can make the helper a private property so that the functions wouldn’t be exposed to the instances of C1, C2, C3. In order to achieve that I had to pass some functions from C1 into the Helper struct.
Question 2:
- Is this problem (hiding implementation details) normally tackled using Helper class (or struct) or is there a more better approach ?
Thanks and regards,
Muthu
···
On 24 Jul 2017, at 4:14 PM, Quinn The Eskimo! via swift-users <swift-users@swift.org> wrote:
On 24 Jul 2017, at 07:04, somu subscribe via swift-users <swift-users@swift.org> wrote:
- Is there a bug in my code which is being detected in Xcode 9 ?
Yes. The problem here is that `doSomething(f1:)` is a mutating function, so it acts like it takes an `inout` reference to `self.helper`. That’s one mutable reference. It then calls `Car.f1()`, which tries to get a non-mutating reference to exactly the same struct. This is outlawed in Swift 4 as part of the memory ownership effort.
You can read more about the specific change in SE-0176 “Enforce Exclusive Access to Memory”.
If so could you please explain and suggest an alternate approach / fix ?
It’s hard to offer concrete suggestions without knowing more about your high-level goals. One option is for `doSomething(f1:)` to pass the `inout` reference through to `f1`. For example:
lazy private var queue = DispatchQueue(label: "my queue")
func test() {
helper.doSomething(f1: f1)
}
func f1() {
queue.async {
_ = self.helper.v1 //Crash - Simultaneous accesses to <memory
, but modification requires exclusive access.
}
}
}
Zhao Xin
···
On Mon, Jul 24, 2017 at 4:22 PM, Quinn "The Eskimo!" via swift-users < swift-users@swift.org> wrote:
On 24 Jul 2017, at 07:04, somu subscribe via swift-users < > swift-users@swift.org> wrote:
> - Is there a bug in my code which is being detected in Xcode 9 ?
Yes. The problem here is that `doSomething(f1:)` is a mutating function,
so it acts like it takes an `inout` reference to `self.helper`. That’s one
mutable reference. It then calls `Car.f1()`, which tries to get a
non-mutating reference to exactly the same struct. This is outlawed in
Swift 4 as part of the memory ownership effort.
You can read more about the specific change in SE-0176 “Enforce Exclusive
Access to Memory”.
> If so could you please explain and suggest an alternate approach / fix ?
It’s hard to offer concrete suggestions without knowing more about your
high-level goals. One option is for `doSomething(f1:)` to pass the `inout`
reference through to `f1`. For example:
Background:
Just a little background into what I was trying to achieve (I could be wrong):
- I have a set of classes C1, C2, C3 which has a lot of common code
- I would like to build something that can be reused without exposing the implementation details. (I can subclass but would expose the underlying functions, same applies to protocol as well)
- I thought I would build helper class / struct which would contain the common code. I can make the helper a private property so that the functions wouldn’t be exposed to the instances of C1, C2, C3. In order to achieve that I had to pass some functions from C1 into the Helper struct.
Question 2:
- Is this problem (hiding implementation details) normally tackled using Helper class (or struct) or is there a more better approach ?
Usually, as long as the protocol doesn't reference self or have associated types, I would use a protocol as the "abstract" type and then you could implement it in either a class or struct.
Thanks Joanna Carter, sorry forgot to mention it uses generics, so would contain associatedtype if protocol is used.
Is the below mentioned approach the usual way to hide implementation details or is there a better approach ?
With this approach, I had to pass functions of C1 as closures into Helper functions.
struct Helper {} //This is could be a protocol / struct / class
class C1 {
private let helper = Helper()
}
Please let me know if the question is off-topic and needs to be posted in a separate thread / elsewhere.
Thanks and regards,
Muthu
···
On 24 Jul 2017, at 5:43 PM, Joanna Carter <joanna@carterconsulting.org.uk> wrote:
Background:
Just a little background into what I was trying to achieve (I could be wrong):
- I have a set of classes C1, C2, C3 which has a lot of common code
- I would like to build something that can be reused without exposing the implementation details. (I can subclass but would expose the underlying functions, same applies to protocol as well)
- I thought I would build helper class / struct which would contain the common code. I can make the helper a private property so that the functions wouldn’t be exposed to the instances of C1, C2, C3. In order to achieve that I had to pass some functions from C1 into the Helper struct.
Question 2:
- Is this problem (hiding implementation details) normally tackled using Helper class (or struct) or is there a more better approach ?
Usually, as long as the protocol doesn't reference self or have associated types, I would use a protocol as the "abstract" type and then you could implement it in either a class or struct.
Thank a lot Quinn, your solution to use inout works well without crashing.
Question 1:
- Also changing Helper to a class doesn’t seem to crash. Is that a solution that wouldn’t cause a crash or just works by chance ?
It is not by chance. It illustrates the key difference between classes and structs: class instances are passed by reference because they have identity. The identity of an object never mutates: If you change `Helper` to a class, then you can also change `helper` property from `var` to `let` and still change the value of `v1` inside `helper`. If this is not clear to you, I recommend you first get a better understanding of differences between value types and reference types and especially learn about object aliasing before deciding which approach is the right approach for you.
Background:
Just a little background into what I was trying to achieve (I could be wrong):
- I have a set of classes C1, C2, C3 which has a lot of common code
- I would like to build something that can be reused without exposing the implementation details. (I can subclass but would expose the underlying functions, same applies to protocol as well)
- I thought I would build helper class / struct which would contain the common code. I can make the helper a private property so that the functions wouldn’t be exposed to the instances of C1, C2, C3. In order to achieve that I had to pass some functions from C1 into the Helper struct.
Question 2:
- Is this problem (hiding implementation details) normally tackled using Helper class (or struct) or is there a more better approach ?
It depends on what you mean by hiding and whether those classes sharing common implementation details also share a common public API (protocol) or ancestry (shared superclass).
Generally, what you call `Helper` is the correct way to go if the following is true:
Your `Helper` makes logical sense as something coherent with its own meaningful properties, so that it can be given a specific name that makes sense (besides a very broad name such as your example `Helper`).
···
On Jul 24, 2017, at 2:38 AM, somu subscribe via swift-users <swift-users@swift.org> wrote:
Thanks and regards,
Muthu
On 24 Jul 2017, at 4:14 PM, Quinn The Eskimo! via swift-users <swift-users@swift.org <mailto:swift-users@swift.org>> wrote:
On 24 Jul 2017, at 07:04, somu subscribe via swift-users <swift-users@swift.org <mailto:swift-users@swift.org>> wrote:
- Is there a bug in my code which is being detected in Xcode 9 ?
Yes. The problem here is that `doSomething(f1:)` is a mutating function, so it acts like it takes an `inout` reference to `self.helper`. That’s one mutable reference. It then calls `Car.f1()`, which tries to get a non-mutating reference to exactly the same struct. This is outlawed in Swift 4 as part of the memory ownership effort.
You can read more about the specific change in SE-0176 “Enforce Exclusive Access to Memory”.
If so could you please explain and suggest an alternate approach / fix ?
It’s hard to offer concrete suggestions without knowing more about your high-level goals. One option is for `doSomething(f1:)` to pass the `inout` reference through to `f1`. For example:
On Mon, Jul 24, 2017 at 4:22 PM, Quinn "The Eskimo!" via swift-users <swift-users@swift.org <mailto:swift-users@swift.org>> wrote:
On 24 Jul 2017, at 07:04, somu subscribe via swift-users <swift-users@swift.org <mailto:swift-users@swift.org>> wrote:
> - Is there a bug in my code which is being detected in Xcode 9 ?
Yes. The problem here is that `doSomething(f1:)` is a mutating function, so it acts like it takes an `inout` reference to `self.helper`. That’s one mutable reference. It then calls `Car.f1()`, which tries to get a non-mutating reference to exactly the same struct. This is outlawed in Swift 4 as part of the memory ownership effort.
You can read more about the specific change in SE-0176 “Enforce Exclusive Access to Memory”.
> If so could you please explain and suggest an alternate approach / fix ?
It’s hard to offer concrete suggestions without knowing more about your high-level goals. One option is for `doSomething(f1:)` to pass the `inout` reference through to `f1`. For example:
The part that tripped me was the fact that value types would be copied every time.
I didn’t realise I wasn’t making a copy of the value type in my program, the same instance of the value type was getting passed (as Quinn and you had pointed out).
Thanks and regards,
Muthu
···
On 31 Jul 2017, at 4:27 AM, Hooman Mehr <hooman@mac.com> wrote:
On Jul 24, 2017, at 2:38 AM, somu subscribe via swift-users <swift-users@swift.org <mailto:swift-users@swift.org>> wrote:
Thank a lot Quinn, your solution to use inout works well without crashing.
Question 1:
- Also changing Helper to a class doesn’t seem to crash. Is that a solution that wouldn’t cause a crash or just works by chance ?
It is not by chance. It illustrates the key difference between classes and structs: class instances are passed by reference because they have identity. The identity of an object never mutates: If you change `Helper` to a class, then you can also change `helper` property from `var` to `let` and still change the value of `v1` inside `helper`. If this is not clear to you, I recommend you first get a better understanding of differences between value types and reference types and especially learn about object aliasing before deciding which approach is the right approach for you.
Background:
Just a little background into what I was trying to achieve (I could be wrong):
- I have a set of classes C1, C2, C3 which has a lot of common code
- I would like to build something that can be reused without exposing the implementation details. (I can subclass but would expose the underlying functions, same applies to protocol as well)
- I thought I would build helper class / struct which would contain the common code. I can make the helper a private property so that the functions wouldn’t be exposed to the instances of C1, C2, C3. In order to achieve that I had to pass some functions from C1 into the Helper struct.
Question 2:
- Is this problem (hiding implementation details) normally tackled using Helper class (or struct) or is there a more better approach ?
It depends on what you mean by hiding and whether those classes sharing common implementation details also share a common public API (protocol) or ancestry (shared superclass).
Generally, what you call `Helper` is the correct way to go if the following is true:
Your `Helper` makes logical sense as something coherent with its own meaningful properties, so that it can be given a specific name that makes sense (besides a very broad name such as your example `Helper`).
Thanks and regards,
Muthu
On 24 Jul 2017, at 4:14 PM, Quinn The Eskimo! via swift-users <swift-users@swift.org <mailto:swift-users@swift.org>> wrote:
On 24 Jul 2017, at 07:04, somu subscribe via swift-users <swift-users@swift.org <mailto:swift-users@swift.org>> wrote:
- Is there a bug in my code which is being detected in Xcode 9 ?
Yes. The problem here is that `doSomething(f1:)` is a mutating function, so it acts like it takes an `inout` reference to `self.helper`. That’s one mutable reference. It then calls `Car.f1()`, which tries to get a non-mutating reference to exactly the same struct. This is outlawed in Swift 4 as part of the memory ownership effort.
You can read more about the specific change in SE-0176 “Enforce Exclusive Access to Memory”.
If so could you please explain and suggest an alternate approach / fix ?
It’s hard to offer concrete suggestions without knowing more about your high-level goals. One option is for `doSomething(f1:)` to pass the `inout` reference through to `f1`. For example: