Re: Work with AddressBook without blocking the main thread

2015-04-25 Thread Quincey Morris
On Apr 25, 2015, at 18:51 , Peter Tomaselli  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  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 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 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  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/ 
> .
>  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 > > 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 
>>> >> > wrote:
>>> 
>>> On Apr 25, 2015, at 17:54 , Peter Tomaselli >>  >> >> 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 easie

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/ 
. 
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  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 
>>  wrote:
>> 
>> On Apr 25, 2015, at 17:54 , Peter Tomaselli > > 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
>>  
>> 
>> 
>> 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, wh

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 
>  wrote:
> 
> On Apr 25, 2015, at 17:54 , Peter Tomaselli  > 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
>  
> 
> 
> 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:54 , Peter Tomaselli  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
 


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 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 
>  wrote:
> 
> On Apr 25, 2015, at 17:06 , Peter Tomaselli  > 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:06 , Peter Tomaselli  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

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