Reputation:
Is there a way for return a value to a function, then invoking a thread in that function? For example:
def foo
return fast_function
Thread.new do
slow_function
end
end
The reason behind this is that both fast_function
and slow_function
write to the same resource. But I want to ensure that fast_function
runs and complete first, and return its value to foo
before slow_function
writes to the shared resource. There are some cases where slow_function
completes before fast_function
and I am hit with a race condition.
EDIT:
More context on the problem. This is related to server-side events I am trying to implement. I am trying to get fast_function
to compute an event id and return and html. While slow_function
is responsible for notifying the client via event id that the process is done. However, in some cases, slow_function
notifies the client before the client event know where to listen, because fast_function
did not return the event id yet.
Upvotes: 1
Views: 247
Reputation: 6026
No, a return will exit the function, it would also exit the function in a yield block. In my opinions there are multiple solutions to this problem.
Actually it would be a perfect fit for a Promise of Concurrent Ruby (https://github.com/ruby-concurrency/concurrent-ruby)
you could use it somewhat like this:
def foo
fast = Concurrent::Promise.execute{ fast_function }
slow = promises[:fast].then{ slow_function }
.on_fullfill{ notify_client }
return fast.value
end
As you can guess it will return the value of your fast function. But it will also call the on_fullfill function (Or a proc) if the slow function has finished. And the most important, it will guarante order.
NOTE: I am not sure if I understood you correctly, if you want to start booth threads at the same time, but ensure that the fast one has finished first. you can do something like this:
fast = Concurrent::Promise.execute{ fast_function }
slow = Concurrent::Promise.execute{ slow_function }
render fast.value # Or what you ever do with the html.
#.value will wait for the Promise to finish.
result slow = slow.value
This way you would start booth functions parallel, but be sure you would get the answer first for the fast one.
Edit 1: I thougth about this, and I am not really sure if you want to have an asynchronous task at all. It is hard to tell since you posted a minimal example (what is correct of coruse). If you just want to have a function which returns botth function returns in the right order, you could just do a yield:
def foo
yield fast_function
yield slow_function
end
Upvotes: 1