Copy link to clipboard
Copied
Since the Photoshop Buffer Suite really doesn't want to be called back from multiple threads (at least that's what I believe I have seen in the docs), what's the best strategy to manage dynamic memory allocation from within a multi-threaded plug-in implementation?
-Noel
Run the UI in the main thread, allocate buffers in the main thread, dispatch work to spawned threads.
And yes, the Plugin API is decidedly not thread safe. There's a lot of plumbing to clean up before it can be thread safe...
Copy link to clipboard
Copied
Run the UI in the main thread, allocate buffers in the main thread, dispatch work to spawned threads.
And yes, the Plugin API is decidedly not thread safe. There's a lot of plumbing to clean up before it can be thread safe...
Copy link to clipboard
Copied
Thanks, but when we switched over to using OpenGL we found the need to render in a separate thread, and it's not practical to pre-allocate everything before kicking it off. We've got it working extremely well using malloc(); I was just curious if I'd missed something. We do inform Photoshop how much (in round terms) we're going to need during DoPrepare().
-Noel
Copy link to clipboard
Copied
Sounds like you've got it.
Some plugin authors forget to tell Photoshop how much space they need in DoPrepare(), and wonder why they run out of allocatable memory...
Copy link to clipboard
Copied
Given that the Buffer Suite is not thread safe, is it safe to call it from multiple threads if all calls are serialized by an external mutex?
And rereading the discussion more closely, it sounds like the Plugin API as a whole is not thread safe. So putting a mutex around just the buffer suite calls maybe won't cut it. But if I serialize all calls into the Plugin API with a single external mutex, could that work?
Copy link to clipboard
Copied
Nope --- call on the main thread only.
And no, the Plugin API is not thread safe at all.
Copy link to clipboard
Copied
You have my sympathies! Multi-threading can be brittle even when it's just your own code to worry about. A plugin API that permits callbacks from unknown code exposes all sorts of composability problems. I can only imagine what the internals must look like such that a big lock around the whole thing isn't sufficient.
Thanks for the quick reply,
Tim.
Copy link to clipboard
Copied
We exposed too many callbacks in the days before multithreading was common.
We're still working on making the code more thread safe.
Copy link to clipboard
Copied
@Chris_Cox, Could you say some words how would it be right to use Multi Threading (OpenMP) in a Plug In?
We have many crashes using OpenMP (For some reason, mainly on OS X).
Thank You.
Copy link to clipboard
Copied
I did come across one more question when testing on huge images the other day...
I was working with a 64 bit build and I noticed the gFilterRecord->bufferSpace field for specifying the memory estimate is an int32.
What should we do in 64 bit operation where the amount of memory we estimate we'll need is multiple gigabytes?
Right now we max the number out at 1 GB (for both 32 or 64 bit builds) because Photoshop didn't seem to like bigger values...
-Noel
Copy link to clipboard
Copied
Hmm, on 64 bit we shouldn't have a problem with just under 2 Gig in the bufferSpace field.
For large buffers, we really want to encourage using the Photoshop allocators.
And yes, we'll probably have to change it in the future, along with other APIs that aren't quite up to 64 bit sizes yet.
Copy link to clipboard
Copied
I try it again with 2^31 - 1 as the max. I don't recall what happened exactly that led us to that decision, but it may have been that we ended up creating a negative number.
While updating the API, please remember that a buffer allocator that's thread safe would be way cool...
-Noel