This is not an issue and only a request for sync version of an API. The file upload has a sync version for blob upload. That helps lib user to easily know the return status and take appropriate action.
Is it possible to have a sync version of IoTHubClient_SendEventAsync. Currently the lib user is expected to align with the callback message and manage message counters to really verify if a message has been sent. Even lib users who are fine with waiting for a message received confirmation, have to do it the async way and which isn't really their need.
Hi @kiranpradeep
You can simulate an Sync send, although the method to do so may be kinda clumsy. I did so by using C++11 with a mutex and an conditionvariable. In C/C++-ish code it should look something like this:
struct SyncHelper {
mutex;
conditionVariable;
SEND_RESULT;
actualCallback;
actualContext;
}
static void sendResultCallback(SEND_RESULT, void* context)
{
SyncHelper* sh = (SyncHelper*) context;
sh->actualCallback(SEND_RESULT, sh->actualContext)
sh->mutex.lock()
sh->SEND_RESULT = SEND_RESULT;
sh->conditionVariable.notify_all();
sh->mutex.unlock();
}
void f(message, callback, context)
{
sh = new SyncHelper;
sh->actualCallback = callback;
sh->actualContext = context;
SendEventAsync(handle, message, sendResultCallback, sh);
sh->mutex.lock();
sh->conditionVariable.wait(sh->mutex);
// Do whatever with return result.
delete sh;
}
I would agree, however, that a method along the lines of IoTHubClient_SendEventAsync would be preferable however. Even if it just "simulates" the outlined process. It would reduce the burden on the ones who use the library.
Hope that helps and kind regards,
Czyba
@czyba Thanks. But we need some thing production grade. 1) block with timeout 2) I use c++11, others might not. 3) handle lost callbacks 4) exception safety etc.
Hi @kiranpradeep,
I am aware that this is not what you are looking for. I am just outlining a process of what can be done with the current methods available. With your requirements in mind:
1.) The only way to have a timeout is to call IoTHubClient_SetOption(handle, "messageTimeout", sometimeoutinms). See this. If you only wish to have a single timeout this might be sufficient, although I'm not aware of what's going to happen if you change the option inbetween two SendEventAsync calls. I agree, however, that setting a per message timeout would be more preferable in any circumstance.
2.) The general outline I wrote in my previous comment does not depend on C++11. Sure, C++11 makes implementing it easier. But you can use your OS's mechanisms instead, i.e. pthread. I still agree that wrapping that functionality within the library would be preferable to have users write it themselves.
3.) What exactly is a lost callback? If you mean that the SDK may NOT call back in certain situations, I can confess that this never happened to me. The callback happens on a success, failure, timeout and termination.
If you mean that the callback "object" may have been destroyed you can use shared_ptr's, unique_ptr's and even std::function to circumvent that issue.
4.) The only exception unsafe operation should be the line:
sh->actualCallback(SEND_RESULT, sh->actualContext)
You can wrap it in a try catch block catching std::exception. You could even extend the struct such that it can remember an exception if one was thrown and rethrow it in the main thread if you so desire.
On another note you could also always try and use the _LL_ (see here) methods to implement a synchronous send. This results, however, in synchronous sends AND receives, since both will happen during _LL_DoWork method calls. Currently, at least in my opinion, you have to choose between: synchronous sending and receiving and asynchronous sending and receiving, although both methods can be used in ways that you can simulate synchronous sending and asynchronous receiving.
I hope your request for that functionality will be heard. I myself would appreciate it if I could send synchronously and receive asynchronously.
Kind Regards,
Christopher Czyba
As @czyba called out, it's possible to build something synchronous out of something async fairly straightforwardly which is why the SDK doesn't have this functionality.
If you're losing callbacks in practice though that's problematic and we'd want to know more about this, however Thanks
Straightforwardly is a relative term here depending on whether your an azure-iot-sdk-c developer or not. There is a lack of consistency in this SDK. Some APIs have *Sync version. Some don't. Shouldn't there be a single policy for all. But, I like the straightforward part of rejecting this request rather than giving lame duck reply of "lets track this in user voice" queue which never gets implemented anyway. Thanks.
No. We are not losing callbacks. It is perfect.