writing to file thread safe

Viewed 36

I have a function that appends data to a file by calling the following extension:

    extension Data {
        func append(fileURL: URL) throws {
            if let fileHandle = FileHandle(forWritingAtPath: fileURL.path) {
                defer {
                    fileHandle.closeFile()
                }
                fileHandle.seekToEndOfFile()
                fileHandle.write(self)
            }
            else {
                try write(to: fileURL, options: .atomic)
            }
        }
    }
    func appendToFile(text:String, url:URL) {
        let data = text.data(using: String.Encoding.utf8)!
        try data.append(fileURL: url)
    }

Now this function is called multiple times within DispatchQueue.global(qos: .userInitiated).async {...} Could this be a problem if the function is called another time while it's still writing? If so, how do I make it thread-safe?

1 Answers

It is indeed a problem if this is called from multiple threads at the same time, they can overwrite each other's content. You need to encapsulate it in some way and ensure only one thread is accessing the file at the same time.

There's countless ways to solve this, from very simple to highly sophisticated:

  • Simply introduce a serial queue and ensure all these operations are always dispatched to that queue. Depending on your needs this is probably the easiest way to solve this.
  • Write an actor that manages all those file accesses. If you're targeting iOS versions not supporting Swift async/await, it's not an option, of course.
  • Go fancy: Write a dedicated object, maybe singleton, that can manage those operations and allows concurrent access to different URLs but ensures the same URL is only accessed serially, via queue or mutex.
Related