Do you need help on a specific subject? Use the contact form (Request a blog entry) on the right hand side.

2016-02-29

Comparing two protocol implementers for identity

An example on how to compare two items that implement the same protocol for their identity. I.e. how to know if two protocol implementers refer to the same item?

I was recently implementing a callback protocol and I needed to be able to manage a list of targets for the callback operations. The basic idea was this:

protocol MyProtocol {
    func myCallback()
}

var callbackTargets: Array<MyProtocol> = []

func add(p: MyProtocol) {
    callbackTargets.append(p)
}

func remove(p: MyProtocol) {
    for (index, q) in callbackTargets.enumerate() {
        if q == p { callbackTargets.removeAtIndex(index) }
    }

}

However that does not compile, it results in the following error:

error: binary operator '==' cannot be applied to two 'MyProtocol' operands

Hmm, ok lets try the '===' operator...

func remove(p: MyProtocol) {
    for (index, q) in callbackTargets.enumerate() {
        if q === p { callbackTargets.removeAtIndex(index) }
    }

}

No luck, the same error:

error: binary operator '===' cannot be applied to two 'MyProtocol' operands

Seems we need to put on our thinking caps...

What is happening?

For the first error, it is probably caused by the fact that no equality operator is defined for the protocol. Since this would impose on the the item that implements the protocol I do not want to add an equality operator. Besides, it would be necessary to compare different kinds of items with each other. Which opens up a whole new can of worms (I think it can be done, but I have not investigated that).

The second error probably comes from the fact that a protocol can be implemented by a value type as well as a class type. A struct can implement a protocol, as can a class. Since it is not possible to compare value types to objects the compiler justifiably complains about it.

There is an additional problem under the hood about which the compiler does not complain, but which is likely to lead to unintended consequences: The array must behave as if it contains "Any" kind of items. Which means that for value types there will be an implicit copy in the "add" function. One of the results will be that when we call the "myCallback" function on the items in the array it won't be on the original item but on a copy of it. Which in my case would be the wrong behaviour.

So, how to solve this?

The first -and most obvious- solution would be to introduce a constraint on the protocol. Implementing a callback really only makes sense for objects. It is unlikely that a value type would need the callback. We could therefore constrain the protocol to class types only:

protocol MyProtocol: class {
    func myCallback()
}

var callbackTargets: Array<MyProtocol> = []

func add(p: MyProtocol) {
    callbackTargets.append(p)
}

func remove(p: MyProtocol) {
    for (index, q) in callbackTargets.enumerate() {
        if q === p { callbackTargets.removeAtIndex(index) }
    }

}

This works. But what if we don't want to add the constraint?

Well, then we need to ensure that the items in the array are all of the same type. For example by making it explicit that we want to deal with pointers:

protocol MyProtocol {
    func myCallback()
}

typealias MyProtocolPointer = UnsafePointer<MyProtocol>

var callbackTargets: Array<MyProtocolPointer> = []

func add(p: MyProtocolPointer) {
    callbackTargets.append(p)
}

func remove(p: MyProtocolPointer) {
    for (index, q) in callbackTargets.enumerate() {
        if q == p { callbackTargets.removeAtIndex(index) }
    }
}

Two possible solutions, I have no preference for either, but in my case it is very unlikely that the callback will ever be implemented on a value type, hence I will constrain the protocol.

PS: Note that in a real application you would want to check if a callback target is  already present in the array with callback targets before appending it.

Happy coding...

Did this help?, then please help out a small independent.
If you decide that you want to make a small donation, you can do so by clicking this
link: a cup of coffee ($2) or use the popup on the right hand side for different amounts.
Payments will be processed by PayPal, receiver will be sales at balancingrock dot nl
Bitcoins will be gladly accepted at: 1GacSREBxPy1yskLMc9de2nofNv2SNdwqH

We don't get the world we wish for... we get the world we pay for.

2016-02-25

NSOutlineView example in Swift

I encountered some strange effects when trying to use the NSOutlineView with pure Swift types. So here is an example on how I got it working using Foundation types.

A sample of the view I wanted to achieve:


This is the base type that I wanted to display in the outline view:

// The Domains Tab

class Domain {
    var name: String = "domain-name.extension"
    var wwwIncluded: Bool = true
    var root: String = "root-folder"
    var forewardUrl: String = ""
}

Which I had to replace with:

// The Domains Tab

class Domain {
    var name: NSString = "domain-name.extension"
    var wwwIncluded: NSNumber = NSNumber(bool: true)
    var root: NSString = "root-folder"
    var forewardUrl: NSString = ""

}


It was not the Bool that caused the problems, but the String. But before I talk about that, let me first show the implementation of the NSOutlineViewDataSource delegate:

var domains = Array<Domain>(arrayLiteral: Domain(), Domain())
@IBOutlet weak var domainNameColumn: NSTableColumn!
@IBOutlet weak var domainValueColumn: NSTableColumn!

extension ConsoleWindowViewController: NSOutlineViewDataSource {
    
    func outlineView(outlineView: NSOutlineView, numberOfChildrenOfItem item: AnyObject?) -> Int {
        if item == nil { return domains.count }
        return 3
    }
    
    func outlineView(outlineView: NSOutlineView, isItemExpandable item: AnyObject) -> Bool {
        return (domains as NSArray).containsObject(item)
    }
    
    func outlineView(outlineView: NSOutlineView, child index: Int, ofItem item: AnyObject?) -> AnyObject {
        if item == nil { return domains[index] }
        for d in domains {
            if item === d {
                switch index {
                case 0: return d.wwwIncluded
                case 1: return d.root
                case 2: return d.forewardUrl
                default:
                    log.atLevelError(id: 0, source: "ConsoleWindowViewController.outlineView-child-ofItem", message: "Index out of range: \(index)")
                }
            }
        }
        return "Error"
    }
    
    // Using "Cell Based" content mode
    func outlineView(outlineView: NSOutlineView, objectValueForTableColumn tableColumn: NSTableColumn?, byItem item: AnyObject?) -> AnyObject? {
        if tableColumn === domainNameColumn {
            for d in domains {
                if item === d { return d.name }
                else if item === d.wwwIncluded { return "Include 'www' prefix" }
                else if item === d.root  { return "Root directory" }
                else if item === d.forewardUrl { return "Foreward to URL" }
            }
        } else if tableColumn === domainValueColumn {
            for d in domains {
                if item === d { return nil }
                else if item === d.wwwIncluded { return (d.wwwIncluded.boolValue ? "yes" : "no") }
                else if item === d.root { return d.root }
                else if item === d.forewardUrl { return (d.forewardUrl.length > 0 ? d.forewardUrl : "-") }
            }
        }
        return nil
    }
}

As you can see, at some point we need to compare the item to the members of the Domain class just to know if the item is referenced. When root is defined as String then this comparison:

item === (d.root as AnyObject

would crash the App at runtime. Strangely enough defining the wwwIncluded as Bool and comparing it as

item === (d.wwwIncluded as AnyObject)

would work fine.

Only by converting the String to a NSString would the App run correctly.

While I do not know what the cause is for this, I don't mind defining the Domain class with Foundation class types as it makes the code a lot more readable. The number of casts is reduced considerably.

Oh, and one more thing: The NSOutlineView in InterfaceBuilder is preset to be "View Based" instead of "Cell Based". If at runtime the view shows you the annoying  "Table View Cell" content, you have probably forgotten to change the Table View - Content Mode from "View Based" to "Cell based":



If you want to use the "View Based" table then do not use

    func outlineView(outlineView: NSOutlineView, objectValueForTableColumn tableColumn: NSTableColumn?, byItem item: AnyObject?) -> AnyObject? {

but use the NSOutlineViewDelegate operation:

    func outlineView(outlineView: NSOutlineView, viewForTableColumn tableColumn: NSTableColumn?, item: AnyObject) -> NSView? {

instead.

Note: While it does work, it turned out that the above code has some not-so-nice properties. I posted an improved example here: Using NSOutlineView in Swift, an example.

Happy coding...

Did this help?, then please help out a small independent.
If you decide that you want to make a small donation, you can do so by clicking this
link: a cup of coffee ($2) or use the popup on the right hand side for different amounts.
Payments will be processed by PayPal, receiver will be sales at balancingrock dot nl
Bitcoins will be gladly accepted at: 1GacSREBxPy1yskLMc9de2nofNv2SNdwqH

We don't get the world we wish for... we get the world we pay for.

2016-02-19

SIGPIPE and multithreading

While working on my socket utilities I ran into a problem: "Thread 1: SIGPIPE"

Hmm.

Wel, lets see what Thread 1 is up to. Turns out it is stopped at a 'select' socket call. But 'select' cannot raise a SIGPIPE can it? No amount of googling did help. SIGPIPE can only occur on 'recv' and 'send'.

So what is going on?

After I added some debug prints I finally found the culprit: It was in thread 4 and it was a call to 'recv'.

So why would Xcode give the message for Thread 1?

This is what I think: the SIGPIPE error -when not handled- leads to termination of the program. This is quite likely a highest level event en thus occurs on the first thread. Hence Thread 1. Thread 1 was not the cause of the problem, but it was the one that is handling the problem.

A bit confusing, and it did cost me a few hours. But that's software development...

Oh, btw, how to get rid of this?

The error is a signal that "the other end" of a connection has closed its side. When a 'recv' or 'send' is called on a socket of which the other side is closed will raise the GIGPIPE exception, which will terminate the application. This can be good if the app is used as part of a series of 'piped' apps. Like most Unix utilities.

However if the app is a server, you want to app to continue working after a SIGPIPE. This can be achieved by setting the socket option SO_NOSIGPIPE to active (1).

A little code segment showing this:

   let receiveSocket = accept(serverSocket, &connectedAddrInfo, &connectedAddrInfoLength)
            
   // Evalute the result of the accept call
            
   if receiveSocket == -1 { // Error
                
      let strerr = String(UTF8String: strerror(errno)) ?? "Unknown error code"
      telemetry?.endTime = NSDate()
      telemetry?.result = .ERROR(message: strerr)
      return .ERROR(message: strerr)
                
   } else// Success, return the accepted socket
                
                
      // ================================================
      // Set the socket option: prevent SIGPIPE exception
      // ================================================
                
      var optval = 1;
                
      let status = setsockopt(
         receiveSocket,
         SOL_SOCKET,
         SO_NOSIGPIPE,
         &optval,
         socklen_t(sizeof(Int)))
                
      if status == -1 {
         let strError = String(UTF8String: strerror(errno)) ?? "Unknown error code"
         close(receiveSocket)
         return .ERROR(message: strError)

      }

To be fair: I am not sure if the 'accept' call will copy the SO_NOSIGPIPE to the newly created receive socket. If it does do that, then setting this option for the server socket would be enough.

Happy coding...

Did this help?, then please help out a small independent.
If you decide that you want to make a small donation, you can do so by clicking this
link: a cup of coffee ($2) or use the popup on the right hand side for different amounts.
Payments will be processed by PayPal, receiver will be sales at balancingrock dot nl
Bitcoins will be gladly accepted at: 1GacSREBxPy1yskLMc9de2nofNv2SNdwqH

We don't get the world we wish for... we get the world we pay for.

2016-02-17

Socket Programming in Swift: Part 8 - Server side considerations

After part 7 detailing the client side of things, what about the server side? What kind of connections does a server see, and how does it respond?

Unfortunately there are many more possibilities than can be described in a single post, so we will restrict ourselves to the following examples:
  1. Setup - Accept - (Receive - Close) - Close
  2. Setup - Accept - ([Receive] - Close) - Close
  3. Setup - Accept - (Receive - Close) - Accept - (Receive - Close) - Close
  4. Setup - Accept - [([Receive] - Close)] - Close
  5. Setup - Accept - [([Receive - [Transfer]] - Close)] - Close

The brackets indicate that the sequence is executed on a different socket than the Setup - Accept () - Close sequence outside the brackets.

The square brackets indicate that the sequence executed multiple times.

To reduce the number of possible scenario's only one receive-transmit scenario is shown. It is probably easy to see how "receive" can be replaced by "receive - transfer" for the other scenario's. Btw: It is of course also possible to skip the receive part entirely and only transfer data to clients.

When I talk about close here, I am assuming a close by the server. If a client closes a connection in between the normal sequence this is considered an error-scenario and is not covered here.

Common:

Before describing the scenario's, it is important to know that when an "accept" call is called on a (properly configured) server socket, it will wait until a client connects. When that happens, the accept call automatically creates a new socket (the client socket) on which all subsequent transfers to/from the connected client happens. Thus after a successful client connection a server has TWO open sockets. One on which it can accept further connections and one for the connected client.

If the server software can handle multiple client connections in parallel, then a second connection request will result in two open sockets for the two connections (assuming the first is not closed yet) and one open socket to accept further connection requests. For a total of THREE open sockets.

1 Setup - Accept - (Receive - Close) - Close


In this scenario the client transfers one data package to the server, and the server accept only one data package before terminating. This is probably not often used, but it can be used if a server has to shut down.
It can also be used to enhance security by timing the window in which a server accepts transfers.

Its advantage is simplicity; the server can be implemented in a single thread.

2 Setup - Accept - ([Receive] - Close) - Close


In this scenario the server accepts only 1 client, but that client can transfer multiple data packages. Once the client is done, it closes the connection. The server closed both its sockets.

In order to differentiate between data packages the client and server must agree on a mechanism to know when one package ends and another starts.

Though slightly more complex than no1, it still can be implemented in a single thread.

3 Setup - Accept - (Receive - Close) - Accept - (Receive - Close) - Close

In this scenario the server accepts two clients and both clients can transfer one data package to the server. However the clients cannot be connected to the server at the same time.
This kind of connection is useful in situations where there is no big harm in a delay before the server accepts a client connection.

Like no1 and no2 before, the server software can still be run in a single thread.

4 Setup - [Accept - ([Receive] - Close)] - Close

With this scenario we leave the single thread applications behind us. Multiple clients can connect -in parallel- to the server. And each client can send multiple data packages.

Not only must the server and client agree on a mechanism to differentiate between data packages, but the server software must also be multithreaded.
After each call to "Accept" the created client socket must be handled in its own thread.

Since there are multiple threads running at the same time, each with its own socket descriptor there is a danger that the server runs out of resources. Either in time or in memory. It is therefor important to manage the number of connections and only accept new connections if the resources are available. Among other this will mean that a time-out must be implemented on open connections.

5 Setup - [Accept - ([Receive - [Transfer]] - Close)] - Close

We finish of these examples with something that I think resembles the HTTP/2 protocol. It is fairly complex, and can profit from a multi-threading implementation even for a single client.

In this example a client connects to the server and sends some data. The server responds by sending multiple data packages back to the client. The client can then send more data to which is again replied by multiple data packages by the server.
In addition, this process can be handled by the server for multiple clients at the same time.

One of the ways this could be implemented server side is as follows:
1 - Setup of the server socket
2 - Accept a client connection
3 - Spin of the receiving of the client data to a new thread.
4 - In that thread receive the data and process the request in another new thread. If data must be returned then start a "data transfer thread" which reads the data to be transferred from a queue. The data receive thread would then fill the queue with data packages as it progresses. Once the received data is completely processed, terminate its thread and terminate the associated transfer thread.
5 - For each new data package received from the client start a new thread, as in point 4.
6 - Keep the connection to the client open until no-activity timeout or until the client closes.

As I said, this is fairly complex and needs to be thought through carefully. Don't simple assume that the above is correct!

Like with no4, the server must manage its resources carefully.

Part 9 is out: SwifterSockets

Check out my Port Spy app in the App Store. A utility that helps you debug your socket based application and includes its own source code. So you can see first hand how to implement socket based io in Swift. And you will be helping this blog!

Enjoy.

Did this help?, then please help out a small independent.
If you decide that you want to make a small donation, you can do so by clicking this
link: a cup of coffee ($2) or use the popup on the right hand side for different amounts.
Payments will be processed by PayPal, receiver will be sales at balancingrock dot nl
Bitcoins will be gladly accepted at: 1GacSREBxPy1yskLMc9de2nofNv2SNdwqH

We don't get the world we wish for... we get the world we pay for.


2016-02-12

OT: Jekyll, a blog aware static site builder.

This post is off-topic.

During the last Xmas season I lost some of my self-hosted Wordpress websites for the second time.  A year before the same thing happened. I do not know what the cause was, I am unable to find a pattern. However I do know that this won't happen again. I quit using Wordpress and went for Jekyll, a static website builder that creates the necessary pages before the user wants them. The result is a much faster website, though at some cost with respect to functionality. That I have to reproduce myself using HTML5, CSS3, SCSS, Kramdown, YAML and Liquid.

Now that looks like a lot of work, and to some extent it is. However the level of control you get in return is amazing.

Anyhow, it is OT for this blog. But it is the reason things went a bit quiet around here. If you are looking for a different content building system for your sites, give Jekyll a try. I am blogging about my experiences here: http://jekyllrien.blogspot.com/

Happy coding...

Did this help?, then please help out a small independent.
If you decide that you want to make a small donation, you can do so by clicking this
link: a cup of coffee ($2) or use the popup on the right hand side for different amounts.
Payments will be processed by PayPal, receiver will be sales at balancingrock dot nl
Bitcoins will be gladly accepted at: 1GacSREBxPy1yskLMc9de2nofNv2SNdwqH

We don't get the world we wish for... we get the world we pay for.