In a Cocoa app, I have a setup like this:
If possible, use NSOperation. It has a -waitUntilFinished method to allow for synchronous computation. You'd just need some thread-safe storage mechanism to allow you to find the NSOperation for the item you're computing, if it already exists—say, an NSLock guarding an NSDictionary.
An NSConditionLock could work nicely here. Perhaps a condition lock associated with each X. Initially condition "dormant" then set to "processing" by the background thread then set to "complete" when it is done. The calling thread could check for the "processing" condition and if it is set, wait until condition "complete" is reached.