Closed tstenner closed 3 years ago
Example from the unit tests:
CHECK_THROWS(lsl::stream_info("", "emptyname"));
CHECK(std::string("The name of a stream must be non-empty.") == lsl_last_error());
That does look pretty good, and I do like the generic implementation. Also nicely declutters some code.
There's one thing that would make sense to tackle here, and that's that the lsl_last_error
wouldn't be thread safe (can return garbled data if some other thread is writing an error message at the same time). I've seen that addressed not with a lock (while it then can't return garbled data anymore, can still return the wrong error message from another thread), but by putting that variable in thread-local storage, so that each thread sees its own version of the last error message. Do you want to give that a shot?
Btw I didn't see the last error being zero-initialized.
There's one thing that would make sense to tackle here, and that's that the
lsl_last_error
wouldn't be thread safe (can return garbled data if some other thread is writing an error message at the same time).
On the one hand "My code makes errors faster than I can check them" is a very specific issue, on the other hand it's literally two changed lines (not including the unit test). Added in 95f8277.
Btw I didn't see the last error being zero-initialized.
Done.
Let's take a simple example:
On a first glance, this should print the time the stream_info was created at.
On a second glance, the format is called
float64
, notdouble64
so an exception should be thrown and the function should return.In reality, a
lsl::stream_info
object is created, but the internal pointer is set to 0 so the call toinfo.created_at()
will dereference a null pointer and everything will crash.This PR first adds the helper macro
LSL_CATCH_EXCEPTIONS
and the helper functioncreate_object_noexcept
for the C-API to convert exceptions to error codes and copy the error message to an internal variable. The last error message can then be retrieved via thelsl_last_error()
function.After that, the C++ wrapper can check for errors (i.e. is the returned pointer valid) or throw an exception with the last error message.