7hacker
7hacker

Reputation: 1978

How to create a function that will eventually return some data and caller must wait

This is actually a Swift Language type of question

I am using Firebase to read/write data

I would like to design a routine in swift that will return eventually. The caller must wait for the routine to complete, so its not a asynchronous, background call actually. Ideally the caller should also be able to:

  1. Determine success or error returns and also process return values

  2. Timeout on the wait if the calling function is taking too long

Inside the function the hold-up is merely an event to Firebase . For example:

func eventuallyReturnFirebase() {

//some stuff

someObj.observeEventType(.ChildAdded, withBlock: {
            snapshot in
            print("\(snapshot.key) -> \(snapshot.value)")
            if (snapshot.key == "foo") {
                // we found value for foo
            }
            if (snapshot.key == "bar") {
                // we found value for bar
            }
        })
//now we can return foo and bar back to caller or some error if we did not
}

Can someone highlight what the Swift language offers in terms of designing such a function and how must the caller be used as well? Hopefully also addressing the 2 ideal conditions as well

Upvotes: 2

Views: 363

Answers (2)

Dim_ov
Dim_ov

Reputation: 1431

If you need to write synchronous wrapper around asynchronous call - you can use semaphores.

I.e. you can write something like this (I'm omiting certain things like types information, so it's kind of swift-like pseudo-code, but this should be enough to get the idea):

func eventuallyReturnFirebase() {

let semaphore = dispatch_semaphore_create(0) //creating a "closed" semaphore
var foo, bar //variables that will hold your return values

someObj.observeEventType(.ChildAdded, withBlock: {
            snapshot in
            print("\(snapshot.key) -> \(snapshot.value)")
            if (snapshot.key == "foo") {
                // we found value for foo
            }
            if (snapshot.key == "bar") {
                // we found value for bar
            }

            //setting values for foo and bar 
            foo = ...  
            bar = ...

            dispatch_semaphore_signal(semaphore) // incrementing semaphore counter
        })

let timeout = dispatch_time(DISPATCH_TIME_NOW, DefaultTimeoutLengthInNanoSeconds)
if dispatch_semaphore_wait(semaphore, timeout) != 0 { // waiting until semaphore conter becomes greater than 0
    print("timed out")
}

return foo, bar
}

Upvotes: 2

Phillip Mills
Phillip Mills

Reputation: 31016

I'd suggest looking at NSCondition as a way of getting both results you want.

The routine that's called starts a timer, starts an asynchronous process, then waits on a condition before returning. The condition is signalled as either the last action of the asynchronous process or by the firing of the timer.

Once the signal allows the routine to continue, it decides whether it was terminated because of time or has something to return.

Upvotes: 1

Related Questions