Swift4.2 does not support stdatomic - what is a simple implementation of an atomic boolean? - swift4.2

I often use stdatomic in ObjectiveC files, but it doesn't yet (will it ever?) appear in Swift. I've found several open source frameworks that appear to offer the same functionality, but what I want is something small and simple.

I discovered the following code that is working well for me:
struct AtomicBoolean {
private var semaphore = DispatchSemaphore(value: 1)
private var b: Bool
var val: Bool {
get {
semaphore.wait()
let tmp = b
semaphore.signal()
return tmp
}
set {
semaphore.wait()
b = newValue
semaphore.signal()
}
}
init(_ initialState: Bool) {
b = initialState
}
}
It sure is small and efficient! DispatchSemaphores are also efficient, only going into kernel space if there is contention (reference Concurrency Programming Guide).
var foo = AtomicBoolean(false)
foo.var = true
if foo.var == true {
print("See!")
}

Related

Swift 2 to swift 3 conversion Midi Input

I'm hoping someone may be able to help i'm using Xcode 8 and swift 3
I have a playground file Xcode 7 swift 2 that involves a Midi callback for Midi Input everything works fine in 7
I tried a conversion to 8 and it brought up errors regarding memory and a few name changes mostly of what i believe to be non serious i also redefined the infinite loop using PlaygroundSupport
However the error i cannot get over involves MyMIDIReadProc at
MIDIInputPortCreate(midiClient, "MidiTest_InPort", MyMIDIReadProc, nil, &inPort);
The error says
Cannot convert value of type '(pktList: UnsafePointer, readProcRefCon: UnsafeMutablePointer, srcConnRefCon: UnsafeMutablePointer) -> Void' to expected argument type 'MIDIReadProc' (aka '#convention(c) (UnsafePointer, Optional>, Optional>) -> ()')
My understanding is that it needs a #convention(c) wrapper of some description inserted. I think i'm on the right track because you can wrap a function but my knowledge of where to put it has run out. Again i was hoping some one might be able to advise
Thanks for reading
apologies for any bad language as i'm self taught
Here is the original Xcode 7 code
import Cocoa
import CoreMIDI
import XCPlayground
func getDisplayName(obj: MIDIObjectRef) -> String
{
var param: Unmanaged<CFString>?
var name: String = "Error";
let err: OSStatus = MIDIObjectGetStringProperty(obj, kMIDIPropertyDisplayName, &param)
if err == OSStatus(noErr)
{
name = param!.takeRetainedValue() as String
}
return name;
}
func MyMIDIReadProc(pktList: UnsafePointer<MIDIPacketList>,
readProcRefCon: UnsafeMutablePointer<Void>, srcConnRefCon: UnsafeMutablePointer<Void>) -> Void
{
let packetList:MIDIPacketList = pktList.memory;
let srcRef:MIDIEndpointRef = UnsafeMutablePointer<MIDIEndpointRef>(COpaquePointer(srcConnRefCon)).memory;
print("MIDI Received From Source: \(getDisplayName(srcRef))");
var packet:MIDIPacket = packetList.packet;
for _ in 1...packetList.numPackets
{
let bytes = Mirror(reflecting: packet.data).children;
var dumpStr = "";
// bytes mirror contains all the zero values in the ridiulous packet data tuple
// so use the packet length to iterate.
var i = packet.length;
for (_, attr) in bytes.enumerate()
{
dumpStr += String(format:"$%02X ", attr.value as! UInt8);
--i;
if (i <= 0)
{
break;
}
}
print(dumpStr)
packet = MIDIPacketNext(&packet).memory;
}
}
var midiClient: MIDIClientRef = 0;
var inPort:MIDIPortRef = 0;
var src:MIDIEndpointRef = MIDIGetSource(0);
MIDIClientCreate("MidiTestClient", nil, nil, &midiClient);
MIDIInputPortCreate(midiClient, "MidiTest_InPort", MyMIDIReadProc, nil, &inPort);
MIDIPortConnectSource(inPort, src, &src);
// Keep playground running
XCPlaygroundPage.currentPage.needsIndefiniteExecution = true;
And here is the Xcode 8 code converted
var str = "Hello, playground"
import Cocoa
import CoreMIDI
import XCPlayground
import PlaygroundSupport
func getDisplayName(obj: MIDIObjectRef) -> String
{
var param: Unmanaged<CFString>?
var name: String = "Error";
let err: OSStatus = MIDIObjectGetStringProperty(obj, kMIDIPropertyDisplayName, &param)
if err == OSStatus(noErr)
{
name = param!.takeRetainedValue() as String
}
return name;
}
func MyMIDIReadProc(pktList: UnsafePointer<MIDIPacketList>,
readProcRefCon: UnsafeMutablePointer<Void>, srcConnRefCon: UnsafeMutablePointer<Void>) -> Void
{
let packetList:MIDIPacketList = pktList.pointee;
let srcRef:MIDIEndpointRef = UnsafeMutablePointer<MIDIEndpointRef>(OpaquePointer(srcConnRefCon)).pointee;
print("MIDI Received From Source: \(getDisplayName(obj: srcRef))");
var packet:MIDIPacket = packetList.packet;
for _ in 1...packetList.numPackets
{
let bytes = Mirror(reflecting: packet.data).children;
var dumpStr = "";
var i = packet.length;
for (_, attr) in bytes.enumerated()
{
dumpStr += String(format:"$%02X ", attr.value as! UInt8);
i -= 1;
if (i <= 0)
{
break;
}
}
print(dumpStr)
packet = MIDIPacketNext(&packet).pointee;
}
}
var midiClient: MIDIClientRef = 0;
var inPort:MIDIPortRef = 0;
var src:MIDIEndpointRef = MIDIGetSource(0);
MIDIClientCreate("MidiTestClient", nil, nil, &midiClient);
MIDIInputPortCreate(midiClient, "MidiTest_InPort", MyMIDIReadProc, nil, &inPort);
MIDIPortConnectSource(inPort, src, &src);
PlaygroundPage.current.needsIndefiniteExecution = true
Pointer types are drastically changed in Swift 3. Many C-based APIs' signatures are changed accordingly.
Following those changes manually would be painful. You can make Swift work for you, with a little modification.
Try changing the function header:
func MyMIDIReadProc(pktList: UnsafePointer<MIDIPacketList>,
readProcRefCon: UnsafeMutablePointer<Void>, srcConnRefCon: UnsafeMutablePointer<Void>) -> Void
{
to a closure declaration:
let MyMIDIReadProc: MIDIReadProc = {pktList, readProcRefCon, srcConnRefCon in
Swift infers argument types perfectly in this style.
You may need to fix pointer type conversion:
let srcRef:MIDIEndpointRef = UnsafeMutablePointer<MIDIEndpointRef>(OpaquePointer(srcConnRefCon)).pointee;
to something like this:
//I'm not sure using `!` is safe here...
let srcRef: MIDIEndpointRef = UnsafeMutablePointer(srcConnRefCon!).pointee
(By the way, the equivalent part in your Xcode 7 code is a little bit redundant. You have no need to use intermediate COpaquePointer there.)
In Swift 3, pointers cannot be nil, and nullable pointers are represented with Optionals. You may need many other fixes to work with C-based APIs in Swift 3.
OOPer is pointing (ahem) you in the right direction. Here is a blog post on using Swift 3 Core MIDI along with a working github repo.
Assuming that you're working with CoreMIDI 1.3 or later, you may have more luck using MIDIInputPortCreateWithBlock instead of MIDIInputPortCreate.
This method takes a Swift block as a parameter instead of requiring an #convention(c) function reference, making it more amenable to use within methods belonging to Swift classes, e.g.:
public func midiReadBlock(ptr: UnsafePointer<MIDIPacketList>, _: UnsafeMutableRawPointer?) -> Void {
let list: MIDIPacketList = ptr.pointee
...
}
You may also find these two extensions useful.
This one (derived from here) allows you to iterate directly over a MIDIPacketList using for pkt in list:
extension MIDIPacketList: Sequence {
public func makeIterator() -> AnyIterator<MIDIPacket> {
var iterator: MIDIPacket?
var nextIndex: UInt32 = 0
return AnyIterator {
nextIndex += 1
if nextIndex > self.numPackets { return nil }
if iterator != nil {
iterator = withUnsafePointer(to: &iterator!) { MIDIPacketNext($0).pointee }
} else {
iterator = self.packet;
}
return iterator
}
}
}
and this one adds a method to a MIDIPacket to extract the contents as a [UInt8] instead of having to use the really broken tuple syntax:
extension MIDIPacket {
public var asArray: [UInt8] {
let mirror = Mirror(reflecting: self.data)
let length = Int(self.length)
var result = [UInt8]()
result.reserveCapacity(length)
for (n, child) in mirror.children.enumerated() {
if n == length {
break
}
result.append(child.value as! UInt8)
}
return result
}
}

Swift 2.0 beta: are protocols kinda broken in Xcode beta 5?

Currently I'm working on my new App written with Swift 2.0. Today I faced two strange errors in Xcode beta 5. I'd love if someone with a previous beta version of Xcode can confirm if I'm right or not. I also could misunderstand something, so I'll appreciate any feedback.
Here is some example code that made me struggle a while:
// Frist bug
protocol SomeProtocol {
var someArray: [String] { get set } // #1 bug
}
extension SomeProtocol {
func someFunction(someString: String) {
self.someArray.append(someString) // #1: Immutable value of type '[String]' only has mutating members named 'append'
}
}
// Second bug
protocol SomeInterfaceProtocol {
var someBool: Bool { get set } // #2 bug
}
class SomeClass: SomeInterfaceProtocol {
var someBool: Bool = false
func returnInterface() -> SomeInterfaceProtocol {
return self
}
}
let someInstance = SomeClass()
// can't set the value
someInstance.returnInterface().someBool = true // #2: Cannot assign to property: function call returns immutable value
The first error can be solved if you add the modifier mutating before the extension func declaration like this:
mutating func someFunction(someString: String) {
I suspect that's a change in the language.
The other one puzzles me as well. At least, here's a work-around:
var c = someInstance.returnInterface()
c.someBool = true
I think the second one isn't a bug as well for the same reason that you can't modify an item in a dictionary directly, or that you can't change elem in for elem in array { ... }.
Something has to be saved to be able to change it. Because you're returning the protocol type, the compiler can't know whether it's a struct or a class, whereas if it's a struct the operation of changing it would have no effect because it's not persisted in any way and structs aren't passed by reference. That's why Thomas' workaround works. Maybe it'll work too if returnInterface returned a class instance, instead of the protocol type.
EDIT: Just tried it out: Indeed it works either if you return SomeClass instead of SomeInterfaceProtocol or if you change the protocol to a class protocol, as it can't be a struct
protocol SomeInterfaceProtocol : class {
var someBool: Bool { get set }
}
class SomeClass: SomeInterfaceProtocol {
var someBool: Bool = false
func returnInterface() -> SomeInterfaceProtocol {
return self
}
}
or
protocol SomeInterfaceProtocol {
var someBool: Bool { get set }
}
class SomeClass: SomeInterfaceProtocol {
var someBool: Bool = false
func returnInterface() -> SomeClass {
return self
}
}
both work

Swift: filter protocol array by comparing types

(first post)
usually im able to find answers here or elsewhere but no luck this time =(
Question: in Swift, how do you filter an array that is of a protocol type by an implementing type supplied as a function parameter?
protocol Aprotocol {
var number:Int { get set }
}
class Aclass: Aprotocol {
var number = 1
}
class AnotherClass: Aprotocol {
var number = 1
}
var array:[Aprotocol] = [ Aclass(), AnotherClass(), Aclass() ]
func foo (parameter:Aprotocol) -> Int {
return array.filter({ /* p in p.self == parameter.self */ }).count
}
var bar:Aprotocol = // Aclass() or AnotherClass()
var result:Int = foo(bar) // should return 2 or 1, depending on bar type
maybe this is not the right approach at all?
thanks!
Here is what I think you want:
return array.filter { (element: Aprotocol) -> Bool in
element.dynamicType == parameter.dynamicType
}.count
But I recommend this, which does the same, but without the useless instance of Aclass() which is passed in the answer on the top. Also this way is faster:
func foo <T: Aprotocol>(type: T.Type) -> Int {
return array.filter { (element: Aprotocol) -> Bool in
element.dynamicType == type
}.count
}
var result:Int = foo(Aclass)
The dynamicType will return the Type of an instance
Very easy:
return array.filter({ parameter.number == $0.number }).count
Kametrixoms solution works (if you use "is T" instead of "== type") but in my case, since i didnt know which implementing class was going to call it, had to go with this solution:
protocol Aprotocol: AnyObject {
var number:Int { get set }
}
class func foo(parameter: AnyObject) -> Int {
return array.filter ({ (element: Aprotocol) -> Bool in
object_getClassName(element) == object_getClassName(parameter)
}).count
}

Swift getter code repetition

I'm trying to have variables in swift that are critical app-wide user settings so they must be persisted to disk after every change. There is a small amount of these variables and I'm content with the first read happening from disk after the app starts.
I have code that looks similar to this:
var _myEnumMember:MyEnum?
var myEnumMember:MyEnum {
get {
if let value = _myEnumMember { // in memory
return value
}
var c:Cache = Cache()
var storedValue:MyEnum? = c.get("SomeStorageKey");
if let value = storedValue { // exists on disk
self.myEnumMember = value // call setter to persist
return self.myEnumMember // call getter again with value set
}
self.myEnumMember = .DefaultValue // assign via setter
return self.rankingDuration // call getter after `set`
}
set (newValue){
self._myEnumMember = newValue // assign to memory
var c:Cache = Cache()
c.put("SomeStorageKey", data: ser) // store in disk
}
I have about 5-6 properties that need to do this - I don't want to repeat myself over and over - is there any way to DRY this code up so I won't have to repeat this logic in several places?
(Note: Asking here and not CR.SE because I'd like answers to explain how to DRY getters/setters in these situations rather than receive critique on a particular piece of code)
I was working on something similar recently - this may be your best bet. I used this as a nested struct, but it doesn't strictly need to be nested.
First, define a LocalCache type that will handle the persistence of your properties:
struct LocalCache {
// set up keys as constants
// these could live in your class instead
static let EnumKey = "EnumKey"
static let IntKey = "IntKey"
static let StringKey = "StringKey"
// use a single cache variable, hopefully?
var cache = Cache()
// in-memory values go in a Dictionary
var localValues: [String: Any] = [:]
// fetch from local storage or from disk
// note that the default value also sets the return type
mutating func fetch<T>(key: String, defaultValue: T) -> T {
if localValues[key] == nil {
localValues[key] = cache.get(key) ?? defaultValue
}
return localValues[key]! as T
}
// save in both local storage and to disk
mutating func store(key: String, _ value: Any) {
localValues[key] = value
cache.put(key, data: value)
}
}
Then add a LocalCache instance to your class, and you can have much simpler getter/setters.
class Test {
// instance of the local cache
var localCache = LocalCache()
var enumPropery: MyEnum {
get { return localCache.fetch(LocalCache.EnumKey, defaultValue: MyEnum.DefaultValue) }
set { localCache.store(LocalCache.EnumKey, newValue) }
}
var intProperty: Int {
get { return localCache.fetch(LocalCache.IntKey, defaultValue: 0) }
set { localCache.store(LocalCache.IntKey, newValue) }
}
var stringProperty: String {
get { return localCache.fetch(LocalCache.StringKey, defaultValue: "---") }
set { localCache.store(LocalCache.StringKey, newValue) }
}
}
If you're using swift in an iOS or OS X context then NSUserDefaults are ABSOLUTELY the right way to do this.
https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSUserDefaults_Class/index.html
http://www.codingexplorer.com/nsuserdefaults-a-swift-introduction/

Swift - using enum in switch statement

I get this error:
'NSNumber' is not a subtype of Cat
Here is the code:
enum Cat:Int {
case Siamese = 0
case Tabby
case Fluffy
}
let cat = indexPath.row as Cat
switch cat {
case .Siamese:
//do something
break;
case .Tabby:
//do something else
break;
case .Fluffy:
break;
}
How can I resolve this error?
Use Cat.fromRaw(indexPath.row) to get the enumeration.
Because the return value of fromRaw() is an optional, use it like thus:
if let cat = Cat.fromRaw (indexPath.row) {
switch cat {
// ...
}
}
The way I handled this same kind of situation in a recent app was to use a Struct consisting entirely of static members, instead of an Enum - in part because I had more information to associate with each option, in part because I got sick of having to call toRaw() and fromRaw() everyplace, and in part because (as your example shows you've discovered) an Enum loses its advantage when it turns out that you can't cycle through, or get a complete list of, the cases.
So, what I did was this:
struct Sizes {
static let Easy = "Easy"
static let Normal = "Normal"
static let Hard = "Hard"
static func sizes () -> [String] {
return [Easy, Normal, Hard]
}
static func boardSize (s:String) -> (Int,Int) {
let d = [
Easy:(12,7),
Normal:(14,8),
Hard:(16,9)
]
return d[s]!
}
}
struct Styles {
static let Animals = "Animals"
static let Snacks = "Snacks"
static func styles () -> [String] {
return [Animals, Snacks]
}
static func pieces (s:String) -> (Int,Int) {
let d = [
Animals:(11,110),
Snacks:(21,210)
]
return d[s]!
}
}
Now when we get to cellForRowAtIndexPath I can talk like this:
let section = indexPath.section
let row = indexPath.row
switch section {
case 0:
cell.textLabel.text = Sizes.sizes()[row]
case 1:
cell.textLabel.text = Styles.styles()[row]
default:
cell.textLabel.text = "" // throwaway
}
Essentially I've just used the two Structs as namespaces with some added intelligence. I'm not saying this is better than what you're doing; they are both eminently Swifty. It's just another idea to consider.

Resources