diff --git a/api/icsneoc/icsneoc.cpp b/api/icsneoc/icsneoc.cpp index 0186dc2..8f9c7ab 100644 --- a/api/icsneoc/icsneoc.cpp +++ b/api/icsneoc/icsneoc.cpp @@ -188,7 +188,7 @@ bool icsneo_disableMessagePolling(const neodevice_t* device) { return device->device->disableMessagePolling(); } -bool icsneo_getMessages(const neodevice_t* device, neomessage_t* messages, size_t* items) { +bool icsneo_getMessages(const neodevice_t* device, neomessage_t* messages, size_t* items, uint64_t timeout) { if(!icsneo_isValidNeoDevice(device)) { ErrorManager::GetInstance().add(APIError::InvalidNeoDevice); return false; @@ -207,7 +207,7 @@ bool icsneo_getMessages(const neodevice_t* device, neomessage_t* messages, size_ std::vector>& storage = polledMessageStorage[device->device]; - if(!device->device->getMessages(storage, *items)) + if(!device->device->getMessages(storage, *items, std::chrono::milliseconds(timeout))) return false; *items = storage.size(); diff --git a/api/icsneolegacy/icsneolegacy.cpp b/api/icsneolegacy/icsneolegacy.cpp index 8dfb692..b2d3658 100644 --- a/api/icsneolegacy/icsneolegacy.cpp +++ b/api/icsneolegacy/icsneolegacy.cpp @@ -111,7 +111,7 @@ int icsneoGetMessages(void* hObject, icsSpyMessage* pMsg, int* pNumberOfMessages neodevice_t* device = (neodevice_t*)hObject; size_t messageCount = 20000; - if(!icsneo_getMessages(device, messages, &messageCount)) + if(!icsneo_getMessages(device, messages, &messageCount, 0)) return false; *pNumberOfMessages = (int)messageCount; diff --git a/device/device.cpp b/device/device.cpp index e0468b1..1b62fcb 100644 --- a/device/device.cpp +++ b/device/device.cpp @@ -99,7 +99,7 @@ std::vector> Device::getMessages() { return ret; } -bool Device::getMessages(std::vector>& container, size_t limit) { +bool Device::getMessages(std::vector>& container, size_t limit, std::chrono::milliseconds timeout) { // A limit of zero indicates no limit if(limit == 0) limit = (size_t)-1; @@ -110,7 +110,11 @@ bool Device::getMessages(std::vector>& container, size_ if(container.size() < limit) container.resize(limit); - size_t actuallyRead = pollingContainer.try_dequeue_bulk(container.data(), limit); + size_t actuallyRead; + if(timeout != std::chrono::milliseconds(0)) + actuallyRead = pollingContainer.wait_dequeue_bulk_timed(container.data(), limit, timeout); + else + actuallyRead = pollingContainer.try_dequeue_bulk(container.data(), limit); if(container.size() > actuallyRead) container.resize(actuallyRead); diff --git a/include/icsneo/device/device.h b/include/icsneo/device/device.h index f7aa05f..466a3f1 100644 --- a/include/icsneo/device/device.h +++ b/include/icsneo/device/device.h @@ -50,7 +50,7 @@ public: void enableMessagePolling(); bool disableMessagePolling(); std::vector> getMessages(); - bool getMessages(std::vector>& container, size_t limit = 0); + bool getMessages(std::vector>& container, size_t limit = 0, std::chrono::milliseconds timeout = std::chrono::milliseconds(0)); size_t getCurrentMessageCount() { return pollingContainer.size_approx(); } size_t getPollingMessageLimit() { return pollingMessageLimit; } void setPollingMessageLimit(size_t newSize) { @@ -145,7 +145,7 @@ private: void updateLEDState(); size_t pollingMessageLimit = 20000; - moodycamel::ConcurrentQueue> pollingContainer; + moodycamel::BlockingConcurrentQueue> pollingContainer; void enforcePollingMessageLimit(); }; diff --git a/include/icsneo/icsneoc.h b/include/icsneo/icsneoc.h index 457447e..2cccc5c 100644 --- a/include/icsneo/icsneoc.h +++ b/include/icsneo/icsneoc.h @@ -188,6 +188,8 @@ extern bool DLLExport icsneo_disableMessagePolling(const neodevice_t* device); * \param[out] messages A pointer to a buffer which neomessage_t structures will be written to. NULL can be passed, which will write the current message count to size. * \param[inout] items A pointer to a size_t which, prior to the call, * holds the maximum number of messages to be written, and after the call holds the number of messages written. + * \param[in] timeout The number of milliseconds to wait for a message to arrive. A value of 0 indicates a non-blocking call. + * Querying for the current message count is always asynchronous and ignores this value. * \returns True if the messages were read out successfully (even if there were no messages to read) or if the count was read successfully. * * Messages are available using this function if icsneo_goOnline() and icsneo_enableMessagePolling() have been called. @@ -202,12 +204,15 @@ extern bool DLLExport icsneo_disableMessagePolling(const neodevice_t* device); * The memory for the data pointer within the neomessage_t is managed by the API. Do *not* attempt to free the data pointer. * The memory will become invalid the next time icsneo_getMessages() is called for this device. * + * \warning Do not call icsneo_close() while another thread is waiting on icsneo_getMessages(). + * Always allow the other thread to timeout first! + * * ``` C * size_t messageCount; - * bool result = icsneo_getMessages(device, NULL, &messageCount); // Reading the message count + * bool result = icsneo_getMessages(device, NULL, &messageCount, 0); // Reading the message count * // Handle errors here * neomessage_t* messages = malloc(messageCount * sizeof(neomessage_t)); // It is also possible and encouraged to use a static buffer - * result = icsneo_getMessages(device, messages, &messageCount); + * result = icsneo_getMessages(device, messages, &messageCount, 0); // Non-blocking * // Handle errors here * for(size_t i = 0; i < messageCount; i++) { * switch(messages[i].type) { @@ -227,7 +232,7 @@ extern bool DLLExport icsneo_disableMessagePolling(const neodevice_t* device); * free(messages); * ``` */ -extern bool DLLExport icsneo_getMessages(const neodevice_t* device, neomessage_t* messages, size_t* items); +extern bool DLLExport icsneo_getMessages(const neodevice_t* device, neomessage_t* messages, size_t* items, uint64_t timeout); /** * \brief Get the maximum number of messages which will be held in the API managed buffer for the specified hardware. @@ -335,7 +340,8 @@ extern bool DLLExport icsneo_settingsApplyDefaultsTemporary(const neodevice_t* d * \param[in] newBaudrate The requested baudrate, with no multipliers. (i.e. 500K CAN should be represented as 500000) * \returns True if the baudrate could be set. * - * In the case of CAN, this function sets the standard CAN baudrate. See icsneo_setFDBaudrate() to set the baudrate for (the baudrate-switched portion of) CAN FD. + * In the case of CAN, this function sets the standard CAN baudrate. + * See icsneo_setFDBaudrate() to set the baudrate for (the baudrate-switched portion of) CAN FD. * * Call icsneo_settingsApply() or similar to make the changes active on the device. */ @@ -550,7 +556,7 @@ fn_icsneo_enableMessagePolling icsneo_enableMessagePolling; typedef bool(*fn_icsneo_disableMessagePolling)(const neodevice_t* device); fn_icsneo_disableMessagePolling icsneo_disableMessagePolling; -typedef bool(*fn_icsneo_getMessages)(const neodevice_t* device, neomessage_t* messages, size_t* items); +typedef bool(*fn_icsneo_getMessages)(const neodevice_t* device, neomessage_t* messages, size_t* items, uint64_t timeout); fn_icsneo_getMessages icsneo_getMessages; typedef size_t(*fn_icsneo_getPollingMessageLimit)(const neodevice_t* device);