Re: NSImage from bitmap - then delete bitmap
On Jul 22, 2016, at 19:29 , Graham Coxwrote: > > If the worker thread is waiting for -performOnMainThread to complete, it > *cannot* possibly get a call from the main thread to terminate I nodded agreement when I first read this, then “but wait!” … Your logic seems flawed on two counts: 1. The selector performed by the worker thread may still be queued, so the main thread is doing something else which may result in an attempt to terminate the worker thread. 2. The worker method performed on the main thread may directly or indirectly lead to an attempt to terminate the worker thread. Both scenarios could cause a deadlock. At least, that’s my attempt at logic. The real problem is that it’s simply a bug to have two threads with mutual, synchronous, unconditional waits. Of course that’s going to deadlock eventually. ___ 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: NSImage from bitmap - then delete bitmap
> On 23 Jul 2016, at 12:45 AM, Trygve Indawrote: > > Because the main thread sometimes needs to ask the worker threads to > terminate. If it does this after performOnMainThread has been called by a > worker thread, but before the main thread has processed it, then the main > thread will block waiting for the worker thread to exit, but the worker > thread has already blocked when it called performOnMainThread. > > Very rare, but it can happen. This is wrong thinking. If the worker thread is waiting for -performOnMainThread to complete, it *cannot* possibly get a call from the main thread to terminate, because the main thread is dealing with whatever the other thread asked it to do. If the worker thread performs a copy and doesn’t wait for the main thread to perform the drawing, then it’s still “blocked” while it’s performing the copy. Either your understanding of the bug is wrong, or there’s somethomg whiffy in your architecture. Usually a worker thread just checks a flag on each loop and falls out when it gets set (by another thread). That flag should be set atomically. There can then be no deadlock. e.g. worker thread: while( self.running ) { // do work window.imageRep = myResult; // window.imageRep is (atomic, copy) [performOnMainThread: window.setNeedsDisplay]; // this is obviously pseudocode! } main thread, when it needs to terminate worker thread: workerThread.running = NO; both workerThread.running and window.imageRep are atomic properties. —Graham ___ 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: kCFStreamPropertySSLSettings
> On Jul 22, 2016, at 2:46 AM, Gerriet M. Denkmannwrote: > > When it gets some streams it will show a panel: > “MyApp wants to sign using key “something” in your keychain” / “Allow” “Deny” Presumably this app is either acting as an SSL server, or is sending SSL clients. Either of those roles involves signing data using the private key associated with the certificate, to prove you own it. If the app hasn’t previously used that private key, the Keychain will ask your permission to let the app use it. That’s the alert. Then it updates the key’s access control list to remember your app has access. But this access is (usually) invalidated when the app binary is modified, so you’ll (usually) see the alert again if you modify the app and run it again. > The problem: sometimes I do NOT get this panel, and the app behaves as if I > had clicked “Deny”. Huh. Had you previously denied the alert? Maybe the security framework hasn’t noticed that the app changed and is still using the old Deny permission set before. > Where is this info: < “MyApp is allowed to use key “something”> stored? In the Keychain item for that key. You can look at and modify the permissions in the Keychain Access app. —Jens ___ 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: Do Debug Apps Expire on iOS?
Debug it some other way than with Xcode. Possibly you have a serious bug, but running under the debugger alters something so that the bug isn't stimulated. ___ 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: NSImage from bitmap - then delete bitmap
Or better yet, have the termination request come from a thread other than the main thread. > On Jul 22, 2016, at 9:38 AM, Alan Snyderwrote: > > >> On Jul 22, 2016, at 7:45 AM, Trygve Inda wrote: >> >> Because the main thread sometimes needs to ask the worker threads to >> terminate. If it does this after performOnMainThread has been called by a >> worker thread, but before the main thread has processed it, then the main >> thread will block waiting for the worker thread to exit, but the worker >> thread has already blocked when it called performOnMainThread. >> >> Very rare, but it can happen. > > This sounds like a bug to me. > > Would this work: The worker thread could set a flag before it calls > performOnMainThread and your thread termination code could do something > different when this flag is set. > ___ 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: NSImage from bitmap - then delete bitmap
> On Jul 22, 2016, at 7:45 AM, Trygve Indawrote: > > Because the main thread sometimes needs to ask the worker threads to > terminate. If it does this after performOnMainThread has been called by a > worker thread, but before the main thread has processed it, then the main > thread will block waiting for the worker thread to exit, but the worker > thread has already blocked when it called performOnMainThread. > > Very rare, but it can happen. This sounds like a bug to me. Would this work: The worker thread could set a flag before it calls performOnMainThread and your thread termination code could do something different when this flag is set. ___ 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: Do Debug Apps Expire on iOS?
Go to Window -> Devices -> View Device Logs -Carl > On Jul 22, 2016, at 4:17 AM, Charles Jenkinswrote: > > Thank you all. I’ll start my research on how to find crash logs. > > On Thu, Jul 21, 2016 at 10:30 AM, Roland King wrote: > >> >>> On 21 Jul 2016, at 22:15, Steve Bird wrote: >>> >>> On Jul 21, 2016, at 10:05 AM, Eric E. Dolecki >> wrote: I believe that debug apps built directly to hardware have a shelf life >> of one year. At least they did. >>> >>> I don’t know, but I would hope that they would pop up some notice like >> “This app has expired. Contact the developer for the current version”. >>> >>> That would seem to be the polite thing to do, rather than driving off >> into the ditch and staying there. >> >> Debug apps expire when your debug provisioning profile expires, which you >> should know because you renewed your membership. >> >> TestFlight apps have a shorter lifetime to encourage developers to release >> test versions on a regular basis and stop TestFlight just being an easy >> mechanism for distributing private apps to your friends for a year at a >> time. >> >> So the original poster most likely has a bug. >> >> >> ___ >> >> 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/cejwork%40gmail.com >> >> This email sent to cejw...@gmail.com >> > > > > -- > > Charles > ___ > > 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/newslists%40autonomy.caltech.edu > > This email sent to newsli...@autonomy.caltech.edu ___ 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: NSImage from bitmap - then delete bitmap
>> Currently it blocks at this point, but I need to avoid that. > > It’s not really clear why this needs to be avoided. The time to draw the > pixels should be a few milliseconds, a small fraction of the time your thread > needs to run, even at its fastest. Because the main thread sometimes needs to ask the worker threads to terminate. If it does this after performOnMainThread has been called by a worker thread, but before the main thread has processed it, then the main thread will block waiting for the worker thread to exit, but the worker thread has already blocked when it called performOnMainThread. Very rare, but it can happen. >> Since it can't >> block, >> the pixels need to be copied to the main thread because as soon as >> they get handed to the main thread, the worker thread will erase the >> original pixel buffer to start drawing a new image into it. > > Copying the image is likely to be just as slow/fast as drawing it, so the copy > isn’t going to help speed up your thread. Both operations have to iterate over > the pixels; drawing *IS* copying. Speed isn't really the issue. The issue is changing the code so that the worker thread never has to block. To do so the pixels need to handed off to the main thread in such a way that the worker thread can then destroy the original pixels (by writing over them with new data) >> The copy needs to exist long enough to be drawn into a window by the main >> thread and can then be released. > > Understood, but you may as well keep it around until the next version of the > image is passed across - the previous one will be released at the same time > when setting the property. Yup - that's possible too. ___ 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: NSImage from bitmap - then delete bitmap
> On 22 Jul 2016, at 11:53 PM, Trygve Indawrote: > > How can I draw the NSImageRep directly into a window? -[NSImageRep drawInRect:fromRect:operation:fraction:respectFlipped:hints:]; i.e. same as NSImage. > > Also, the main pixel buffer is updated slowly (it takes a long time to > draw). So once the worker thread is done, it needs to pass off those pixels > to the main thread to be drawn. > > Currently it blocks at this point, but I need to avoid that. It’s not really clear why this needs to be avoided. The time to draw the pixels should be a few milliseconds, a small fraction of the time your thread needs to run, even at its fastest. > Since it can't > block, > the pixels need to be copied to the main thread because as soon as > they get handed to the main thread, the worker thread will erase the > original pixel buffer to start drawing a new image into it. Copying the image is likely to be just as slow/fast as drawing it, so the copy isn’t going to help speed up your thread. Both operations have to iterate over the pixels; drawing *IS* copying. > The copy needs to exist long enough to be drawn into a window by the main > thread and can then be released. Understood, but you may as well keep it around until the next version of the image is passed across - the previous one will be released at the same time when setting the property. —Graham ___ 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: NSImage from bitmap - then delete bitmap
> >> On 22 Jul 2016, at 4:08 PM, Trygve Indawrote: >> >> I don't think the second part will work because of my workflow: >> >> At Launch: Create pixel buffer that is 1000 x 1000 pixels >> >> Looping thread >> 1. Fill pixel buffer with pixels based on some algorithm >> 2. create an NSImage with these pixels >> 3. pass it to the main thread to be drawn in a window >> Restart the loop with a slightly modified algorithm >> >> If calling this: >> [myImage addRepresentation:theBitmapIMadeFirst]; >> >> Only causes the NSImage to retain it, then when I change the pixels in the >> bitmap, they get changed in the NSImage. >> >> I need the NSImage to keep the pixels as they existed when I created it. > > > Do you? > > Once the image is drawn into the window, it’s effectively copied to the > window’s backing store, so there’s already a second copy of the pixels. > > The only situation that might cause a problem is if the window can possibly be > called upon to redraw at a time when the bitmap is being updated but hasn’t > yet completed. If the code that fills the buffer is synchronous, that can > never happen. If the code is asynchronous (e.g. on a second thread), then you > *might* want a copy of the bitmap, but only if drawing it halfway through > updating would actually be bad - that depends entirely on what is being drawn. > If it’s a minor/subtle change, it may not be noticeable. > > With half an eye on performance, if you *do* strictly need a copy of the > bitmap, note that NSBitmapImageRep conforms to NSCopying. You don’t have to > turn it into a TIFF and back again. > > Also, you don’t even need an NSImage - the NSImageRep can be drawn directly. How can I draw the NSImageRep directly into a window? Also, the main pixel buffer is updated slowly (it takes a long time to draw). So once the worker thread is done, it needs to pass off those pixels to the main thread to be drawn. Currently it blocks at this point, but I need to avoid that. Since it can't block, the pixels need to be copied to the main thread because as soon as they get handed to the main thread, the worker thread will erase the original pixel buffer to start drawing a new image into it. The copy needs to exist long enough to be drawn into a window by the main thread and can then be released. ___ 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: NSImage from bitmap - then delete bitmap
>> This is how it works now, but we are running into a rare deadlock situation >> where the main thread asks the worker thread to end (and waits until it does >> so) while the worker thread is waiting for the image to be displayed. > > If the window has a imageRep property that is (atomic, copy) you shouldn’t run > into a deadlock where the window tries to terminate the thread and it happens > to be calling that method at the time. If you go with Roland’s suggestion, it > doesn’t need to be copy, it can simply be strong. But make it atomic, as the > property will need to be accessed from both the main and the worker threads > and the rep must be in a viable state at both times. Ultimately there needs to be more than one copy of the pixels because as soon as the worker thread is done building the image, it hands it off to the main thread to be displayed. Currently it blocks until the main thread displays it, so only one set of pixels is needed. But to prevent deadlock, the worker thread really needs to just hand of a copy of the pixels, then erase the original pixels and start a new image. [bitmapImageRep copy] might be the best solution here. T. ___ 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: Do Debug Apps Expire on iOS?
Thank you all. I’ll start my research on how to find crash logs. On Thu, Jul 21, 2016 at 10:30 AM, Roland Kingwrote: > > > On 21 Jul 2016, at 22:15, Steve Bird wrote: > > > > > >> On Jul 21, 2016, at 10:05 AM, Eric E. Dolecki > wrote: > >> > >> I believe that debug apps built directly to hardware have a shelf life > of > >> one year. At least they did. > > > > I don’t know, but I would hope that they would pop up some notice like > “This app has expired. Contact the developer for the current version”. > > > > That would seem to be the polite thing to do, rather than driving off > into the ditch and staying there. > > Debug apps expire when your debug provisioning profile expires, which you > should know because you renewed your membership. > > TestFlight apps have a shorter lifetime to encourage developers to release > test versions on a regular basis and stop TestFlight just being an easy > mechanism for distributing private apps to your friends for a year at a > time. > > So the original poster most likely has a bug. > > > ___ > > 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/cejwork%40gmail.com > > This email sent to cejw...@gmail.com > -- Charles ___ 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
kCFStreamPropertySSLSettings
I have an app (macOS 11.6) which uses kCFStreamPropertySSLSettings. When it gets some streams it will show a panel: “MyApp wants to sign using key “something” in your keychain” / “Allow” “Deny” When I click “Deny” the streams get NSOSStatusErrorDomain errSecAuthFailed. Else (clicked “Allow”) the app proceeds normally. So far so good. The problem: sometimes I do NOT get this panel, and the app behaves as if I had clicked “Deny”. Before (11.5) quitting/restarting the app fixed this problem. But in 11.6 I sometimes have to quit/restart a lot. Where is this info: < “MyApp is allowed to use key “something”> stored? How to reset this (to force the app show the panel)? Gerriet. ___ 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: NSImage from bitmap - then delete bitmap
> On 22 Jul 2016, at 5:30 PM, Quincey Morris >wrote: > > On Jul 22, 2016, at 00:08 , Graham Cox wrote: >> >> If the thread building images never goes faster than once per second, the >> time to draw the image is a fraction of that - I’m sure 60fps is achievable, >> so making the thread wait for the drawing to be done isn’t going to hold it >> up significantly. > > (I’ve done something like this, though it was a couple of years ago, so the > same performance characteristics cannot be assumed.) > > With the sequence: > > worker thread -> NSBitmapImageRep -> main thread -> window > > not even 24 fps was achievable, for anything but fairly small images (say, > less than one quarter of a 21-inch non-Retina screen). That’s because a > bitmap image rep isn’t the internal representation of anything, so there > always a copy or two, along with a possible pixel format translation, and a > colorspace mapping. A possible optimisation there would be to use -[NSView bitmapImageRepForCachingDisplayInRect:] which returns a rep that matches the backing store format and colorspace, so copying is fast. That might put more strain on the renderer code though, which has to deal with the format it finds, not one it created. > OTOH, I’m not sure 60fps is being asked for, unless that comes from your > special knowledge of what the app does. It was less than 1 fps per worker > thread, and if there are 60+ worker threads, there are likely other > performance issues as well. > It’s not being asked for - 1fps is the fastest. But I meant that if the drawing time is in the 60fps ballpark, then that part isn’t going to hold up the 1fps worker thread significanty. I *think* (correct me if I’m wrong Trygve) that there’s only one such worker thread. > On 22 Jul 2016, at 5:19 PM, Trygve Inda wrote: > > This is how it works now, but we are running into a rare deadlock situation > where the main thread asks the worker thread to end (and waits until it does > so) while the worker thread is waiting for the image to be displayed. If the window has a imageRep property that is (atomic, copy) you shouldn’t run into a deadlock where the window tries to terminate the thread and it happens to be calling that method at the time. If you go with Roland’s suggestion, it doesn’t need to be copy, it can simply be strong. But make it atomic, as the property will need to be accessed from both the main and the worker threads and the rep must be in a viable state at both times. —Graham ___ 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: NSImage from bitmap - then delete bitmap
On Jul 22, 2016, at 00:08 , Graham Coxwrote: > > If the thread building images never goes faster than once per second, the > time to draw the image is a fraction of that - I’m sure 60fps is achievable, > so making the thread wait for the drawing to be done isn’t going to hold it > up significantly. (I’ve done something like this, though it was a couple of years ago, so the same performance characteristics cannot be assumed.) With the sequence: worker thread -> NSBitmapImageRep -> main thread -> window not even 24 fps was achievable, for anything but fairly small images (say, less than one quarter of a 21-inch non-Retina screen). That’s because a bitmap image rep isn’t the internal representation of anything, so there always a copy or two, along with a possible pixel format translation, and a colorspace mapping. Plus multithreading overheads like locks. The details will depend on the Mac, the OS version and the display. If something performant is necessary, then the best approach is probably to use CVPixelBuffer instead. However, the learning curve for this is pretty horrendous, particular when dealing with isolated still images rather than video, so I would not suggest going there unless absolutely necessary. OTOH, I’m not sure 60fps is being asked for, unless that comes from your special knowledge of what the app does. It was less than 1 fps per worker thread, and if there are 60+ worker threads, there are likely other performance issues as well. ___ 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: NSImage from bitmap - then delete bitmap
> >> On 22 Jul 2016, at 4:40 PM, Trygve Indawrote: >> >> >>> With half an eye on performance, if you *do* strictly need a copy of the >>> bitmap, note that NSBitmapImageRep conforms to NSCopying. You don’t have to >>> turn it into a TIFF and back again. >>> >>> Also, you don’t even need an NSImage - the NSImageRep can be drawn directly. >> >> >> A little deeper discussion of how my app works. > > I have an idea I know what this app is, so I understand what you need to do. I > won’t name names if you don’t :) I believe I am a registered user. > > >> >> I have a background worker thread whose purpose is to generate a continuous >> series of NSImages - from one per second to one every 5 minutes or so). I >> may have several of these worker threads working on different images. >> >> The thread starts by making a pixel buffer using: >> >> [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL .. >> >> Then the thread goes into a loop where on each pass it draws the correct >> image into this pixel buffer. >> >> After the image is drawn it need to be handed off to the main thread to be >> drawn into a window. >> >> As soon as it is handed off, the thread starts drawing a new image, >> destroying the pixels used to create the image that was just handed off. >> >> It is likely that the image will not be received by the main thread and >> drawn into the window before the pixels in the NSBitmapImageRep are >> destroyed (because it the thread is now drawing a new image). >> >> So how is the best way to take my NSBitmapImageRep, and hand it off to the >> main thread in such a way that I can destroy the pixels immediately while >> the main thread keeps them? >> >> Would it be best to just call [myImagerep copy], and hand that to the main >> thread, and let the main thread release it once it has draw it into the >> window? >> > > > I have an idea I know what this app is, so I understand what you need to do. I > won’t name names if you don’t :) I believe I am a registered user.> I think > you have two choices. Without naming names, I am sure your hunch is accurate. > You can pass the rep to the window using > performSelectorOnMainThread:withObject:waitUntilDone: passing YES for wait > until done, in which case your worker thread will be stalled just long enough > to draw the image and copy to the backing store. After that you’re free to > continue modifying the rep. This is how it works now, but we are running into a rare deadlock situation where the main thread asks the worker thread to end (and waits until it does so) while the worker thread is waiting for the image to be displayed. I have never seen it happen here, but I have tracked it down from hang reports and need to figure out the best way to hand the pixels off to the main thread in such a way that there are no dependencies on the original pixel buffer because as soon as the pixels are handed to the main thread, the worker thread will be changing the pixels in the original buffer. ___ 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: NSImage from bitmap - then delete bitmap
> On 22 Jul 2016, at 5:00 PM, Roland Kingwrote: > > Since you need the data to persist for display whilst you write a new image > that means there’s two separate buffers, there has to be Not sure there HAS to be. Whether it’s the easiest approach is another matter. If the thread building images never goes faster than once per second, the time to draw the image is a fraction of that - I’m sure 60fps is achievable, so making the thread wait for the drawing to be done isn’t going to hold it up significantly. You’re going to waste exactly the same amount of time doing a copy. Your suggestion of making a new buffer is a good one, as there’s no wasted time, provided that the worker thread does set every pixel. Otherwise it’s going to have to clear it and you’re back to a pass over the pixels which takes the same time as the copy/draw, etc. But is it worth it to save the 4MB per bitmap? Once upon a time the answer would definitely be yes, but 4MB isn’t much these days. —Graham ___ 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: NSImage from bitmap - then delete bitmap
> On 22 Jul 2016, at 14:40, Trygve Indawrote: > > >> With half an eye on performance, if you *do* strictly need a copy of the >> bitmap, note that NSBitmapImageRep conforms to NSCopying. You don’t have to >> turn it into a TIFF and back again. >> >> Also, you don’t even need an NSImage - the NSImageRep can be drawn directly. > > > > So how is the best way to take my NSBitmapImageRep, and hand it off to the > main thread in such a way that I can destroy the pixels immediately while > the main thread keeps them? > > Would it be best to just call [myImagerep copy], and hand that to the main > thread, and let the main thread release it once it has draw it into the > window? > I’d have said the best way is to create a new image buffer for each new image you draw, draw into it and hand it off, then make another new one instead of trying to use one single one per thread. Creating them is cheap, it’s basically malloc(). Since you need the data to persist for display whilst you write a new image that means there’s two separate buffers, there has to be. So either you make a copy, which means going through the expense of copying it, or you just hand it off and start a new one, which doesn’t. When the main thread has finished with it it can dispose of the old buffer. ___ 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: NSImage from bitmap - then delete bitmap
> On 22 Jul 2016, at 4:40 PM, Trygve Indawrote: > > >> With half an eye on performance, if you *do* strictly need a copy of the >> bitmap, note that NSBitmapImageRep conforms to NSCopying. You don’t have to >> turn it into a TIFF and back again. >> >> Also, you don’t even need an NSImage - the NSImageRep can be drawn directly. > > > A little deeper discussion of how my app works. I have an idea I know what this app is, so I understand what you need to do. I won’t name names if you don’t :) I believe I am a registered user. > > I have a background worker thread whose purpose is to generate a continuous > series of NSImages - from one per second to one every 5 minutes or so). I > may have several of these worker threads working on different images. > > The thread starts by making a pixel buffer using: > > [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL .. > > Then the thread goes into a loop where on each pass it draws the correct > image into this pixel buffer. > > After the image is drawn it need to be handed off to the main thread to be > drawn into a window. > > As soon as it is handed off, the thread starts drawing a new image, > destroying the pixels used to create the image that was just handed off. > > It is likely that the image will not be received by the main thread and > drawn into the window before the pixels in the NSBitmapImageRep are > destroyed (because it the thread is now drawing a new image). > > So how is the best way to take my NSBitmapImageRep, and hand it off to the > main thread in such a way that I can destroy the pixels immediately while > the main thread keeps them? > > Would it be best to just call [myImagerep copy], and hand that to the main > thread, and let the main thread release it once it has draw it into the > window? > I think you have two choices. You can pass the rep to the window using performSelectorOnMainThread:withObject:waitUntilDone: passing YES for wait until done, in which case your worker thread will be stalled just long enough to draw the image and copy to the backing store. After that you’re free to continue modifying the rep. Or you can copy the rep and not bother waiting. One way to do that easily is to make the window’s ‘imageRep’ propery ‘copy’ and it’ll do it for you. But you’ll also need to call -setNeedsDisplay: on the main thread, again without waiting. I don’t think there’s any real advantage one way or the other - one will use quite a lot of memory, the other might be ever so slightly slower. Classic tradeoff. Note that unless you deliberately mark the window as needing display, your window will NEVER draw from the rep, even if the user moves it revealing a covered portion - that will be filled from the backing store. —Graham ___ 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: NSImage from bitmap - then delete bitmap
> With half an eye on performance, if you *do* strictly need a copy of the > bitmap, note that NSBitmapImageRep conforms to NSCopying. You don’t have to > turn it into a TIFF and back again. > > Also, you don’t even need an NSImage - the NSImageRep can be drawn directly. A little deeper discussion of how my app works. I have a background worker thread whose purpose is to generate a continuous series of NSImages - from one per second to one every 5 minutes or so). I may have several of these worker threads working on different images. The thread starts by making a pixel buffer using: [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL .. Then the thread goes into a loop where on each pass it draws the correct image into this pixel buffer. After the image is drawn it need to be handed off to the main thread to be drawn into a window. As soon as it is handed off, the thread starts drawing a new image, destroying the pixels used to create the image that was just handed off. It is likely that the image will not be received by the main thread and drawn into the window before the pixels in the NSBitmapImageRep are destroyed (because it the thread is now drawing a new image). So how is the best way to take my NSBitmapImageRep, and hand it off to the main thread in such a way that I can destroy the pixels immediately while the main thread keeps them? Would it be best to just call [myImagerep copy], and hand that to the main thread, and let the main thread release it once it has draw it into the window? ___ 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: NSImage from bitmap - then delete bitmap
> On 22 Jul 2016, at 4:08 PM, Trygve Indawrote: > > I don't think the second part will work because of my workflow: > > At Launch: Create pixel buffer that is 1000 x 1000 pixels > > Looping thread > 1. Fill pixel buffer with pixels based on some algorithm > 2. create an NSImage with these pixels > 3. pass it to the main thread to be drawn in a window > Restart the loop with a slightly modified algorithm > > If calling this: > [myImage addRepresentation:theBitmapIMadeFirst]; > > Only causes the NSImage to retain it, then when I change the pixels in the > bitmap, they get changed in the NSImage. > > I need the NSImage to keep the pixels as they existed when I created it. Do you? Once the image is drawn into the window, it’s effectively copied to the window’s backing store, so there’s already a second copy of the pixels. The only situation that might cause a problem is if the window can possibly be called upon to redraw at a time when the bitmap is being updated but hasn’t yet completed. If the code that fills the buffer is synchronous, that can never happen. If the code is asynchronous (e.g. on a second thread), then you *might* want a copy of the bitmap, but only if drawing it halfway through updating would actually be bad - that depends entirely on what is being drawn. If it’s a minor/subtle change, it may not be noticeable. With half an eye on performance, if you *do* strictly need a copy of the bitmap, note that NSBitmapImageRep conforms to NSCopying. You don’t have to turn it into a TIFF and back again. Also, you don’t even need an NSImage - the NSImageRep can be drawn directly. —Graham ___ 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: NSImage from bitmap - then delete bitmap
On Jul 22, 2016, at 1:08 AM, Trygve Indawrote: > >> But that’s not a great way to do this. You’ve made an image, you’ve encoded >> it >> as TIFF data, then you’ve made a new image, which has decoded the TIFF data >> to >> make a new image rep/bitmap. >> >> You could just add the representation directly to a new NSImage (warning: >> typed into Mail, check method names): >> >> NSImage* myImage = [[NSImage alloc] initWithSize:NSMakeSize(width,height)]; >> >> [myImage addRepresentation:theBitmapIMadeFirst]; >> >> [theBitmapIMadeFirst release]; // because NSImage retained it > > > I don't think the second part will work because of my workflow: > > At Launch: Create pixel buffer that is 1000 x 1000 pixels > > Looping thread > 1. Fill pixel buffer with pixels based on some algorithm > 2. create an NSImage with these pixels > 3. pass it to the main thread to be drawn in a window > Restart the loop with a slightly modified algorithm > > If calling this: > [myImage addRepresentation:theBitmapIMadeFirst]; > > Only causes the NSImage to retain it, then when I change the pixels in the > bitmap, they get changed in the NSImage. > > I need the NSImage to keep the pixels as they existed when I created it. Hint: NSBitmapImageRep conforms to the NSCopying protocol. Regards, Ken ___ 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: NSImage from bitmap - then delete bitmap
> >> On 22 Jul 2016, at 3:37 PM, Trygve Indawrote: >> >> I create an NSBitmapImageRep: >> >> [[[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL >> pixelsWide:pixelSize.width >> pixelsHigh:pixelSize.height >> bitsPerSample:8 >> samplesPerPixel:4 >> hasAlpha:YES >> isPlanar:NO >> colorSpaceName:NSDeviceRGBColorSpace >> bitmapFormat:NSAlphaFirstBitmapFormat >> bytesPerRow:pixelSize.width * 4 >> bitsPerPixel:32] >> >> I then get the address by sending a "bitmapData" message to the object >> >> After filling it with image data, I call: >> >> NSImage* image = >> [[NSImage alloc] initWithData:[myImageRep TIFFRepresentation]]; >> >> So now I have an NSImage. What happens if I delete/release myImageRep (my >> NSBitmapImageRep)? > > Nothing. The rep isn’t doing anything after this point; you can release it > safely. > >> Has the call to NSImage copied my pixels so that they are self-contained >> within the NSImage? > > Yes. > > But that’s not a great way to do this. You’ve made an image, you’ve encoded it > as TIFF data, then you’ve made a new image, which has decoded the TIFF data to > make a new image rep/bitmap. > > You could just add the representation directly to a new NSImage (warning: > typed into Mail, check method names): > > NSImage* myImage = [[NSImage alloc] initWithSize:NSMakeSize(width,height)]; > > [myImage addRepresentation:theBitmapIMadeFirst]; > > [theBitmapIMadeFirst release]; // because NSImage retained it I don't think the second part will work because of my workflow: At Launch: Create pixel buffer that is 1000 x 1000 pixels Looping thread 1. Fill pixel buffer with pixels based on some algorithm 2. create an NSImage with these pixels 3. pass it to the main thread to be drawn in a window Restart the loop with a slightly modified algorithm If calling this: [myImage addRepresentation:theBitmapIMadeFirst]; Only causes the NSImage to retain it, then when I change the pixels in the bitmap, they get changed in the NSImage. I need the NSImage to keep the pixels as they existed when I created 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: NSImage from bitmap - then delete bitmap
On Jul 22, 2016, at 12:37 AM, Trygve Indawrote: > > I create an NSBitmapImageRep: > > [[[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL > pixelsWide:pixelSize.width > pixelsHigh:pixelSize.height > bitsPerSample:8 > samplesPerPixel:4 > hasAlpha:YES > isPlanar:NO > colorSpaceName:NSDeviceRGBColorSpace > bitmapFormat:NSAlphaFirstBitmapFormat > bytesPerRow:pixelSize.width * 4 > bitsPerPixel:32] > > I then get the address by sending a "bitmapData" message to the object > > After filling it with image data, I call: > > NSImage* image = > [[NSImage alloc] initWithData:[myImageRep TIFFRepresentation]]; Aside from your primary question, don't do this. Use -initWithSize: and then directly add the representation to the image using -addRepresentation:. > So now I have an NSImage. What happens if I delete/release myImageRep (my > NSBitmapImageRep)? > > Has the call to NSImage copied my pixels so that they are self-contained > within the NSImage? The general answer is you don't know and you shouldn't care. It is the responsibility of the framework to do what's necessary. It may have retained the image rep or retained some private NSData object that represented the pixels or copied the data or whatever. The memory management conventions of Cocoa are designed to be local in nature. Generally, you do not need to know what other code is doing. (Exceptions are documented.) You only need to get your part correct, where you retain objects if you need to ensure they live beyond the current scope (if you don't already have an ownership reference to them, as from +alloc, -copy…, etc.) and you release ownership references after you're done with those objects. You just assume that the other parts of the code follow the rules, too, and everything works. You said "delete/release myImageRep". That "delete" represents incorrect thinking on your part. You only ever release your ownership reference to the object. You can't know whether something else also has an ownership reference to it, so you can't know when the object is deleted/deallocated. In this particular case, you're using -TIFFRepresentation which creates a data object of a TIFF image file format. Since that's not the same format as the pixel data you stored via -bitmapData, it's very likely an independent object. Also, there's no reason for the image rep to keep any reference to it around. For example, you could modify the bitmap data some more and generate a new TIFF data object and that would be different from the first. Surely, it's clear to you that such modifications to the bitmap data of the image rep must not modify the TIFF data that you created earlier. Then, -initWithData: decodes the TIFF data and makes a new NSImage with whatever representations it needs. Because of the layers of abstraction/conversion that the data went through, it's very unlikely that the new NSImage or representations have any references to the original image rep. Regards, Ken ___ 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: NSImage from bitmap - then delete bitmap
> On 22 Jul 2016, at 3:37 PM, Trygve Indawrote: > > I create an NSBitmapImageRep: > > [[[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL > pixelsWide:pixelSize.width > pixelsHigh:pixelSize.height > bitsPerSample:8 > samplesPerPixel:4 > hasAlpha:YES > isPlanar:NO > colorSpaceName:NSDeviceRGBColorSpace > bitmapFormat:NSAlphaFirstBitmapFormat > bytesPerRow:pixelSize.width * 4 > bitsPerPixel:32] > > I then get the address by sending a "bitmapData" message to the object > > After filling it with image data, I call: > > NSImage* image = > [[NSImage alloc] initWithData:[myImageRep TIFFRepresentation]]; > > So now I have an NSImage. What happens if I delete/release myImageRep (my > NSBitmapImageRep)? Nothing. The rep isn’t doing anything after this point; you can release it safely. > Has the call to NSImage copied my pixels so that they are self-contained > within the NSImage? Yes. But that’s not a great way to do this. You’ve made an image, you’ve encoded it as TIFF data, then you’ve made a new image, which has decoded the TIFF data to make a new image rep/bitmap. You could just add the representation directly to a new NSImage (warning: typed into Mail, check method names): NSImage* myImage = [[NSImage alloc] initWithSize:NSMakeSize(width,height)]; [myImage addRepresentation:theBitmapIMadeFirst]; [theBitmapIMadeFirst release]; // because NSImage retained it … done. All NSImage is is a “box” in which a bunch of NSImageReps reside. It sometimes makes those reps itself from data, etc, but you can make them yourself and add them. It’s way more efficient. —Graham ___ 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