Re: Work with AddressBook without blocking the main thread

2015-04-25 Thread Peter Tomaselli
Yup, that’s my problem exactly. You explained it much better than I could!

To be honest, I don’t have a real good reason for not using the main thread at 
the moment—it seems fine, performance-wise, for what I am doing. But I was 
interested in hearing if there was a more performant approach I might be 
missing, if only to satisfy my curiosity. Most of the info on the web about 
this is tons of GCD contortions that, from what I can tell, are missing the 
point.

So with respect to spinning up a thread to “keep around”, just point me in the 
right direction here (this would be new stuff for me): is it NSThread I should 
look at?

Appreciate it,

Peter

 On Apr 25, 2015, at 8:33 PM, Quincey Morris 
 quinceymor...@rivergatesoftware.com wrote:
 
 On Apr 25, 2015, at 17:06 , Peter Tomaselli peter.tomase...@icloud.com 
 mailto:peter.tomase...@icloud.com wrote:
 
 The crux of my problem is that, according to the docs, 
 ABAddressBookRequestAccessWithCompletion’s completion handler “is called on 
 an arbitrary queue”. However, ABAddressBookRequestAccessWithCompletion 
 accepts as an argument an ABAddressBookRef that, presumably, has already 
 been created. 
 
 I’m not sure how to proceed here. GCD serial queues can guarantee serial 
 access to stuff, but it doesn’t seem like they provide any guarantees about 
 your code executing on any one thread in particular. So, it doesn’t seem 
 like GCD helps me here.
 
 So you won’t be able to issue any AB… API calls from the completion handler 
 directly. Instead, you’ll need to know which thread you created the 
 ABAddressBookRef on, and arrange to issue the subsequent calls from there.
 
 This is easy if you created the ABAddressBookRef on the main thread, because 
 the completion handler can use 'dispatch_async (dispatch_get_main_queue (), 
 …’ to get back to the main thread.
 
 What you won’t be able to do is create the ABAddressBookRef via a block 
 dispatched to some non-main GCD queue, because you won’t necessarily be able 
 to return to the thread the queue was using at the time. In other words, if 
 you need to create the ABAddressBookRef on a background thread for some 
 reason, you’ll have to do it on a thread you create for yourself, and keep 
 the thread around.
 
 But I wouldn’t expect you’d need to create the ABAddressBookRef anywhere but 
 on the main thread, right?
 

___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Work with AddressBook without blocking the main thread

2015-04-25 Thread Quincey Morris
On Apr 25, 2015, at 17:54 , Peter Tomaselli peter.tomase...@icloud.com wrote:
 
 I don’t have a real good reason for not using the main thread at the 
 moment—it seems fine, performance-wise, for what I am doing.

The point of these restrictions on ABAddressBook is that it’s *already* an 
asynchronous API. There’s no synchronous waiting that would block the main 
thread, and the fact that the completion handler is called on an “arbitrary” 
thread suggests that all the heavy lifting is already done on a background 
thread, outside of your control. For that reason, I can’t think of a reason why 
you’d ever want to start from a background thread.

Also, do you have a good reason for sticking with the C API? What about using 
the Cocoa API? [ABAddressBook sharedAddressBook] doesn’t seem to have the 
same-thread requirement, though [ABAddress addressBook] does.

(Note that in the current state of OS X or iOS, it’s a mistake to assume that 
the C version of an API is more performant than the Obj-C version. It’s almost 
always better just to use the one that’s easier to use, and that’s almost 
always the Obj-C version.)

 But I was interested in hearing if there was a more performant approach I 
 might be missing, if only to satisfy my curiosity. Most of the info on the 
 web about this is tons of GCD contortions that, from what I can tell, are 
 missing the point.
 
 So with respect to spinning up a thread to “keep around”, just point me in 
 the right direction here (this would be new stuff for me): is it NSThread I 
 should look at?

https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/Multithreading/CreatingThreads/CreatingThreads.html
 
https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/Multithreading/CreatingThreads/CreatingThreads.html

However, there’s no reason to believe that using a background thread is going 
to perform better. All you’d be moving to the background thread, I think, is 
the creation of the ABAddressBookRef data structure itself, which isn’t going 
to make any difference to anything.



___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Work with AddressBook without blocking the main thread

2015-04-25 Thread Peter Tomaselli
Hi there. I’m writing my first iPhone application and trying to figure out how 
to best work—asynchronously—with the AddressBook API. I’m building against iOS 
8.

I’m not experienced with Cocoa, but based on the docs, as well as 
seemingly-credible SO answers (particularly this one[0]), my understanding is 
that the ABAddressBook APIs are not only thread-unsafe but also thread… affine? 
Or whatever? In other words, it is not enough to access AddressBook objects in 
a serial fashion, they must actually be accessed from the same thread on which 
they were created.

The crux of my problem is that, according to the docs, 
ABAddressBookRequestAccessWithCompletion’s completion handler “is called on an 
arbitrary queue”. However, ABAddressBookRequestAccessWithCompletion accepts as 
an argument an ABAddressBookRef that, presumably, has already been created. 

I’m not sure how to proceed here. GCD serial queues can guarantee serial access 
to stuff, but it doesn’t seem like they provide any guarantees about your code 
executing on any one thread in particular. So, it doesn’t seem like GCD helps 
me here.

Finally, just to clarify my question a little:

- I am interested in doing this “the right way”, and without any third-party 
libraries, as a learning experience.
- I’d like to end up with a simple wrapper class that accepts blocks (I 
imagine) of the type void (^)(ABAddressBookRef) and executes them—abstracting 
away the authorization checking stuff, which I think I understand—without 
blocking the UI.

Thanks for any suggestions!

Peter

[0] http://stackoverflow.com/a/10844781
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Work with AddressBook without blocking the main thread

2015-04-25 Thread Peter Tomaselli
Thanks for the reply. Well, now you’ve got me doubting myself. This is for iOS. 
Isn’t the C API the only option on that platform? 

I am planning on doing some work with the address book that doesn’t seem to be 
directly supported in the API (basically, I want to display all the email 
addresses in the address book that meet certain criteria). For this, I was 
assuming I’d have to grab pretty much all the email addresses from the book and 
iterate through them, bucketing as I go. 

This is all in my head so far, but if my ABAddressBookRef must live on the main 
thread forevermore, doesn’t that mean my “filtering” code must also run on the 
main thread? This is the reason I am concerned about blocking. 

Instead, my hope was to build a small wrapper class for the ’book that would 
accept blocks, run them off away from the main thread, and call back to the UI 
when done. 

It sounds like that’s maybe what is available on OS X already? But this is an 
iPhone app. I’ll check out the threading stuff; sounds like that might be fun 
to try anyway.

Appreciate the help,

Peter

 On Apr 25, 2015, at 9:23 PM, Quincey Morris 
 quinceymor...@rivergatesoftware.com wrote:
 
 On Apr 25, 2015, at 17:54 , Peter Tomaselli peter.tomase...@icloud.com 
 mailto:peter.tomase...@icloud.com wrote:
 
 I don’t have a real good reason for not using the main thread at the 
 moment—it seems fine, performance-wise, for what I am doing.
 
 The point of these restrictions on ABAddressBook is that it’s *already* an 
 asynchronous API. There’s no synchronous waiting that would block the main 
 thread, and the fact that the completion handler is called on an “arbitrary” 
 thread suggests that all the heavy lifting is already done on a background 
 thread, outside of your control. For that reason, I can’t think of a reason 
 why you’d ever want to start from a background thread.
 
 Also, do you have a good reason for sticking with the C API? What about using 
 the Cocoa API? [ABAddressBook sharedAddressBook] doesn’t seem to have the 
 same-thread requirement, though [ABAddress addressBook] does.
 
 (Note that in the current state of OS X or iOS, it’s a mistake to assume that 
 the C version of an API is more performant than the Obj-C version. It’s 
 almost always better just to use the one that’s easier to use, and that’s 
 almost always the Obj-C version.)
 
 But I was interested in hearing if there was a more performant approach I 
 might be missing, if only to satisfy my curiosity. Most of the info on the 
 web about this is tons of GCD contortions that, from what I can tell, are 
 missing the point.
 
 So with respect to spinning up a thread to “keep around”, just point me in 
 the right direction here (this would be new stuff for me): is it NSThread I 
 should look at?
 
 https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/Multithreading/CreatingThreads/CreatingThreads.html
  
 https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/Multithreading/CreatingThreads/CreatingThreads.html
 
 However, there’s no reason to believe that using a background thread is going 
 to perform better. All you’d be moving to the background thread, I think, is 
 the creation of the ABAddressBookRef data structure itself, which isn’t going 
 to make any difference to anything.
 

___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Work with AddressBook without blocking the main thread

2015-04-25 Thread Quincey Morris
On Apr 25, 2015, at 17:06 , Peter Tomaselli peter.tomase...@icloud.com wrote:

 The crux of my problem is that, according to the docs, 
 ABAddressBookRequestAccessWithCompletion’s completion handler “is called on 
 an arbitrary queue”. However, ABAddressBookRequestAccessWithCompletion 
 accepts as an argument an ABAddressBookRef that, presumably, has already been 
 created. 
 
 I’m not sure how to proceed here. GCD serial queues can guarantee serial 
 access to stuff, but it doesn’t seem like they provide any guarantees about 
 your code executing on any one thread in particular. So, it doesn’t seem like 
 GCD helps me here.

So you won’t be able to issue any AB… API calls from the completion handler 
directly. Instead, you’ll need to know which thread you created the 
ABAddressBookRef on, and arrange to issue the subsequent calls from there.

This is easy if you created the ABAddressBookRef on the main thread, because 
the completion handler can use 'dispatch_async (dispatch_get_main_queue (), …’ 
to get back to the main thread.

What you won’t be able to do is create the ABAddressBookRef via a block 
dispatched to some non-main GCD queue, because you won’t necessarily be able to 
return to the thread the queue was using at the time. In other words, if you 
need to create the ABAddressBookRef on a background thread for some reason, 
you’ll have to do it on a thread you create for yourself, and keep the thread 
around.

But I wouldn’t expect you’d need to create the ABAddressBookRef anywhere but on 
the main thread, right?



___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Work with AddressBook without blocking the main thread

2015-04-25 Thread Roland King

 
 Also, the post served to bring dispatch_get_current_queue() to my attention, 
 which seems quite handy.
 

Don’t get too excited on that score, it was deprecated 2 OS revisions ago 
despite there being some legitimate use cases for it. My bug report on that got 
closed with the “not changing it” response. 


___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Work with AddressBook without blocking the main thread

2015-04-25 Thread Quincey Morris
On Apr 25, 2015, at 18:51 , Peter Tomaselli peter.tomase...@icloud.com wrote:
 
 This is for iOS. Isn’t the C API the only option on that platform? 

Yes, by the time I got there I didn’t notice that it was OS X only.

I realize I was wrong, too, to call the address book API asynchronous. When you 
get down to searching for records, it does seem pretty synchronous. Under the 
circumstances, starting your own captive background thread for doing the bulk 
search seems like a good idea.

 On Apr 25, 2015, at 20:19 , Roland King r...@rols.org wrote:
 
 Also, the post served to bring dispatch_get_current_queue() to my attention, 
 which seems quite handy.
 
 
 Don’t get too excited on that score, it was deprecated 2 OS revisions ago 
 despite there being some legitimate use cases for it. My bug report on that 
 got closed with the “not changing it” response.


There was a discussion a while back, maybe here on this list, on the pitfalls 
of trying to get the current queue. An Apple engineer explained some of what 
can go wrong. It’s all terribly subtle, and the only safe answer is “don’t do 
this”. That was why I punted earlier, and just said you can’t do it.

___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Work with AddressBook without blocking the main thread

2015-04-25 Thread Peter Tomaselli
Ha, great link! It was fun reading about the possible pitfalls here. Database 
corruption simply by reading improperly? Yikes!

Also, the post served to bring dispatch_get_current_queue() to my attention, 
which seems quite handy.

This fella does not mention how he handles the whole “the [authorization 
request] completion handler is called on an arbitrary queue” issue, but 
probably the ‘solution’ there is for me to make a strategic retreat and prompt 
for access slightly before, instead of exactly at the moment that, I need 
access to the AB. 

Thanks for all the help, Quincey and Roland. I may still try this with a 
private thread and a runloop, just for fun. :)

Peter

 On Apr 25, 2015, at 10:27 PM, Roland King r...@rols.org wrote:
 
 I had trouble believing there was an API left which was really thread-tied - 
 until I convinced myself that this one really is. I wonder why, underlying 
 SQL implementation perhaps? 
 
 In the course of hunting around I found a blog entry here 
 http://adrian.schoenig.me/blog/2012/05/05/ios-addressbook-framework-and-gcd/ 
 http://adrian.schoenig.me/blog/2012/05/05/ios-addressbook-framework-and-gcd/.
  It ended with this update which is interesting if not authoritative
 
 After having had a chat with Apple engineers, the recommended way is the 
 following: Create address book references on the fly whenever you need them. 
 Do not bother keeping them around since they are lightweight and fast to 
 create. The performance issue that I experienced was due to doing the initial 
 search and the cache for the address book not yet being warmed up. You could 
 just create a fake query at first to warm it up, but it is not recommended.”
 
 if you don’t need to keep a long-running persistent reference to the address 
 book, you may well be able to create them when you need them, use them 
 immediately and then throw them away again. You may be able to create lots of 
 them in different blocks on possibly different background queues at the same 
 time and effectively parallelise the whole thing. 
 
 You could, again if you don’t just need one true ABAddressBookRef, squirrel 
 created ones away in thread local storage, then they’re guaranteed to be 
 per-thread, but I’d only even try that rather dubious solution if analysis 
 showed that creating and destroying them was causing performance issues. 
 
 On 26 Apr 2015, at 09:51, Peter Tomaselli peter.tomase...@icloud.com 
 mailto:peter.tomase...@icloud.com wrote:
 
 Thanks for the reply. Well, now you’ve got me doubting myself. This is for 
 iOS. Isn’t the C API the only option on that platform? 
 
 I am planning on doing some work with the address book that doesn’t seem to 
 be directly supported in the API (basically, I want to display all the email 
 addresses in the address book that meet certain criteria). For this, I was 
 assuming I’d have to grab pretty much all the email addresses from the book 
 and iterate through them, bucketing as I go. 
 
 This is all in my head so far, but if my ABAddressBookRef must live on the 
 main thread forevermore, doesn’t that mean my “filtering” code must also run 
 on the main thread? This is the reason I am concerned about blocking. 
 
 Instead, my hope was to build a small wrapper class for the ’book that would 
 accept blocks, run them off away from the main thread, and call back to the 
 UI when done. 
 
 It sounds like that’s maybe what is available on OS X already? But this is 
 an iPhone app. I’ll check out the threading stuff; sounds like that might be 
 fun to try anyway.
 
 Appreciate the help,
 
 Peter
 
 On Apr 25, 2015, at 9:23 PM, Quincey Morris 
 quinceymor...@rivergatesoftware.com 
 mailto:quinceymor...@rivergatesoftware.com wrote:
 
 On Apr 25, 2015, at 17:54 , Peter Tomaselli peter.tomase...@icloud.com 
 mailto:peter.tomase...@icloud.com mailto:peter.tomase...@icloud.com 
 mailto:peter.tomase...@icloud.com wrote:
 
 I don’t have a real good reason for not using the main thread at the 
 moment—it seems fine, performance-wise, for what I am doing.
 
 The point of these restrictions on ABAddressBook is that it’s *already* an 
 asynchronous API. There’s no synchronous waiting that would block the main 
 thread, and the fact that the completion handler is called on an 
 “arbitrary” thread suggests that all the heavy lifting is already done on a 
 background thread, outside of your control. For that reason, I can’t think 
 of a reason why you’d ever want to start from a background thread.
 
 Also, do you have a good reason for sticking with the C API? What about 
 using the Cocoa API? [ABAddressBook sharedAddressBook] doesn’t seem to have 
 the same-thread requirement, though [ABAddress addressBook] does.
 
 (Note that in the current state of OS X or iOS, it’s a mistake to assume 
 that the C version of an API is more performant than the Obj-C version. 
 It’s almost always better just to use the one that’s easier to use, and 
 that’s almost always the Obj-C version.)
 
 But I was 

Re: Work with AddressBook without blocking the main thread

2015-04-25 Thread Roland King
I had trouble believing there was an API left which was really thread-tied - 
until I convinced myself that this one really is. I wonder why, underlying SQL 
implementation perhaps? 

In the course of hunting around I found a blog entry here 
http://adrian.schoenig.me/blog/2012/05/05/ios-addressbook-framework-and-gcd/ 
http://adrian.schoenig.me/blog/2012/05/05/ios-addressbook-framework-and-gcd/. 
It ended with this update which is interesting if not authoritative

After having had a chat with Apple engineers, the recommended way is the 
following: Create address book references on the fly whenever you need them. Do 
not bother keeping them around since they are lightweight and fast to create. 
The performance issue that I experienced was due to doing the initial search 
and the cache for the address book not yet being warmed up. You could just 
create a fake query at first to warm it up, but it is not recommended.”

if you don’t need to keep a long-running persistent reference to the address 
book, you may well be able to create them when you need them, use them 
immediately and then throw them away again. You may be able to create lots of 
them in different blocks on possibly different background queues at the same 
time and effectively parallelise the whole thing. 

You could, again if you don’t just need one true ABAddressBookRef, squirrel 
created ones away in thread local storage, then they’re guaranteed to be 
per-thread, but I’d only even try that rather dubious solution if analysis 
showed that creating and destroying them was causing performance issues. 

 On 26 Apr 2015, at 09:51, Peter Tomaselli peter.tomase...@icloud.com wrote:
 
 Thanks for the reply. Well, now you’ve got me doubting myself. This is for 
 iOS. Isn’t the C API the only option on that platform? 
 
 I am planning on doing some work with the address book that doesn’t seem to 
 be directly supported in the API (basically, I want to display all the email 
 addresses in the address book that meet certain criteria). For this, I was 
 assuming I’d have to grab pretty much all the email addresses from the book 
 and iterate through them, bucketing as I go. 
 
 This is all in my head so far, but if my ABAddressBookRef must live on the 
 main thread forevermore, doesn’t that mean my “filtering” code must also run 
 on the main thread? This is the reason I am concerned about blocking. 
 
 Instead, my hope was to build a small wrapper class for the ’book that would 
 accept blocks, run them off away from the main thread, and call back to the 
 UI when done. 
 
 It sounds like that’s maybe what is available on OS X already? But this is an 
 iPhone app. I’ll check out the threading stuff; sounds like that might be fun 
 to try anyway.
 
 Appreciate the help,
 
 Peter
 
 On Apr 25, 2015, at 9:23 PM, Quincey Morris 
 quinceymor...@rivergatesoftware.com wrote:
 
 On Apr 25, 2015, at 17:54 , Peter Tomaselli peter.tomase...@icloud.com 
 mailto:peter.tomase...@icloud.com wrote:
 
 I don’t have a real good reason for not using the main thread at the 
 moment—it seems fine, performance-wise, for what I am doing.
 
 The point of these restrictions on ABAddressBook is that it’s *already* an 
 asynchronous API. There’s no synchronous waiting that would block the main 
 thread, and the fact that the completion handler is called on an “arbitrary” 
 thread suggests that all the heavy lifting is already done on a background 
 thread, outside of your control. For that reason, I can’t think of a reason 
 why you’d ever want to start from a background thread.
 
 Also, do you have a good reason for sticking with the C API? What about 
 using the Cocoa API? [ABAddressBook sharedAddressBook] doesn’t seem to have 
 the same-thread requirement, though [ABAddress addressBook] does.
 
 (Note that in the current state of OS X or iOS, it’s a mistake to assume 
 that the C version of an API is more performant than the Obj-C version. It’s 
 almost always better just to use the one that’s easier to use, and that’s 
 almost always the Obj-C version.)
 
 But I was interested in hearing if there was a more performant approach I 
 might be missing, if only to satisfy my curiosity. Most of the info on the 
 web about this is tons of GCD contortions that, from what I can tell, are 
 missing the point.
 
 So with respect to spinning up a thread to “keep around”, just point me in 
 the right direction here (this would be new stuff for me): is it NSThread I 
 should look at?
 
 https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/Multithreading/CreatingThreads/CreatingThreads.html
  
 https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/Multithreading/CreatingThreads/CreatingThreads.html
 
 However, there’s no reason to believe that using a background thread is 
 going to perform better. All you’d be moving to the background thread, I 
 think, is the creation of the ABAddressBookRef data structure itself, which 
 isn’t going to make any