Is it safe to call sc_fifo::nb_write() from a SC_THREAD process? - systemc

I am converting some of my code from a SC_THREAD to a SC_METHOD. My question is, do I need to stop using the sc_fifo class? I realize an SC_METHOD should not call sc_fifo.write() because this uses a wait call which is not allowed for functions that cannot be suspended. However, sc_fifo provides non-blocking versions of various functions and potentially I could use these instead. Some of the documentation I've read indicates you should never use sc_fifo from a SC_METHOD at all but provided no justification.
Here is a sample of code I am currently using.
class Example : public sc_module {
public:
sc_fifo<int> myFifo;
sc_in<bool> clock_in;
SC_HAS_PROCESS(Example);
// constructor
Example(sc_module_name name) : sc_module(name) {
SC_METHOD(read);
sensitive << clock_in;
}
void read() {
int value = -1;
bool success = myFifo.nb_read(value);
if (success) { cout << "Read value " << value << endl; }
else { cout << "No read done but that's okay." << endl; }
}
};
int sc_main(int argc, char* argv[]) {
sc_clock clock("clock");
Example example("example");
example.clock_in(clock);
sc_start(10, SC_NS);
return 0;
}
This throws no errors even though I am calling an sc_fifo function from a SC_METHOD. Is it bad policy to use nb_read() from inside a SC_METHOD? If so why?

Using sc_fifo non-blocking calls from SC_METHOD should be fine.
I have not found any place in standard manual that prohibits it.

Neither nb_read, nor nb_write, as their names suggest, call wait internally so it's fine to use them from an SC_METHOD.
While your example code works, it's rather inefficient when things are put into the fifo infrequently. If you want your code to be more event driven, you could make the SC_METHOD sensitive to sc_fifo.data_written_event(); then it will only be called when something is actually written to the fifo (though it's still a good idea to check that nb_read returns true in case something else pulled from the same fifo). Of course, this would skip your "No read done but that's okay." prints.
Also, I think the title of your question probably meant to ask about calling nb_write from SC_METHOD rather than SC_THREAD.

Related

how spawn and post works with asio?

// I asked this question
// https://stackoverflow.com/questions/61026135/asio-use-future-instead-of-yieldec
// and comments lead to need to modify code of answer and put in in this new
// question.
// I tried to ask questions in form of code trials and causes of writing them
// or how i under stand them
// asio_packaged_task.cpp : Defines the entry point for the console application.
//#include "stdafx.h"
#define BOOST_COROUTINES_NO_DEPRECATION_WARNING
#include <boost/asio.hpp>
#include <boost/asio/spawn.hpp>
#include <boost/asio/use_future.hpp>
#include <boost/bind.hpp>
#include <iostream>
using boost::system::error_code;
namespace asio = boost::asio;
template <typename Token>
auto async_meaning_of_life(bool success, Token&& token) {
#if BOOST_VERSION >= 106600
using result_type =
typename asio::async_result<std::decay_t<Token>, void(error_code, int)>;
typename result_type::completion_handler_type handler(
std::forward<Token>(token));
result_type result(handler);
#else
typename asio::handler_type<Token, void(error_code, int)>::type handler(
std::forward<Token>(token));
asio::async_result<decltype(handler)> result(handler);
#endif
if (success)
handler(error_code{}, 42); // 4-18-2020 this line happens when
// async_meaning_of_life work is done,this
// line is calling the handler and passing it
// the result of async_meaning_of_life
// function which here for simplicity are
// supplied as error_code{} and 42
else
handler(asio::error::operation_aborted, 0);
return result.get();
}
void using_yield_ec(asio::yield_context yield) {
for (bool success : { true, false }) {
boost::system::error_code ec;
auto answer = async_meaning_of_life(success, yield[ec]);
std::cout << __FUNCTION__ << ": Result: " << ec.message() << "\n";
std::cout << __FUNCTION__ << ": Answer: " << answer << "\n";
}
}
void using_yield_catch(asio::yield_context yield) {
for (bool success : { true, false })
try {
auto answer = async_meaning_of_life(success, yield);
std::cout << __FUNCTION__ << ": Answer: " << answer << "\n";
} catch (boost::system::system_error const& e) {
std::cout << __FUNCTION__ << ": Caught: " << e.code().message()
<< "\n";
}
}
// 4-18-2020 something interesting happens here,when we call the function
// using_future or using_handler in the same thread we get into these two
// functions then inside them we call async_meaning_of_life which is an
// initiating function ,the async_meaning_of_life has two parts: its code which
// ends before if(success) then it calls the completion token passed to it which
// is promise OR lambda "it might be fuction object ,functor,function pointer, "
// using handler(error,42) where handler represents the true handler type
// according to the token passed to function. then it returns the result by
// result.get to using_future or using_handler. inside using handler we notice
// that code returns back to lambda after handler(error,42) .if completion token
// were bind or function object,we would have seen code jumping to bound
// function or function object
void using_future() {
for (bool success : { true, false })
try {
auto answer = async_meaning_of_life(success, asio::use_future);
std::cout << __FUNCTION__ << ": Answer: " << answer.get() << "\n";
} catch (boost::system::system_error const& e) {
std::cout << __FUNCTION__ << ": Caught: " << e.code().message()
<< "\n";
}
}
void using_handler() {
for (bool success : { true, false })
async_meaning_of_life(success, [](error_code ec, int answer) {
std::cout << "using_handler: Result: " << ec.message() << "\n";
std::cout << "using_handler: Answer: " << answer << "\n";
});
}
void print(const boost::system::error_code& /*e*/) {
std::cout << "Hello, world!" << std::endl;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////
template <typename Token>
auto async_meaning_of_life_composed(bool success, Token&& token) {
#if BOOST_VERSION >= 106600
using result_type =
typename asio::async_result<std::decay_t<Token>, void(error_code, int)>;
typename result_type::completion_handler_type handler(
std::forward<Token>(token));
result_type result(handler);
#else
typename asio::handler_type<Token, void(error_code, int)>::type handler(
std::forward<Token>(token));
asio::async_result<decltype(handler)> result(handler);
#endif
// here i will add intermediate initiating functions
async_meaning_of_life(success, [](error_code ec, int answer) {
std::cout << "using_handler: Result: " << ec.message() << "\n";
std::cout << "using_handler: Answer: " << answer << "\n";
});
try {
auto answer = async_meaning_of_life(success, asio::use_future);
std::cout << __FUNCTION__ << ": Answer: " << answer.get() << "\n";
} catch (boost::system::system_error const& e) {
std::cout << __FUNCTION__ << ": Caught: " << e.code().message() << "\n";
}
// using_yield_ec(asio::yield_context yield);
// spawn(svc, using_yield_ec);
//////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////
if (success)
handler(error_code{}, 42); // 4-18-2020 this line happens when
// async_meaning_of_life work is done,this
// line is calling the handler and passing it
// the result of async_meaning_of_life
// function which here for simplicity are
// supplied as error_code{} and 42
else
handler(asio::error::operation_aborted, 0);
return result.get();
}
void using_future_composed() {
for (bool success : { true, false })
try {
auto answer =
async_meaning_of_life_composed(success, asio::use_future);
std::cout << __FUNCTION__ << ": Answer: " << answer.get() << "\n";
} catch (boost::system::system_error const& e) {
std::cout << __FUNCTION__ << ": Caught: " << e.code().message()
<< "\n";
}
}
int main() {
asio::io_service svc;
boost::asio::steady_timer t(svc, boost::asio::chrono::seconds(45));
// this function returns immediately and make new thread
t.async_wait(&print);
// this function returns immediately>>>>also it adds 1 out standing work to
// svc.is async_wait body runned in main threaed OR in another thread????if
// it is ran in another thread,how immediate return happens"not
// blocking"??why async_meaning is not returning immediately like
// async_wait?
auto answer = async_meaning_of_life(true, asio::use_future);
// this function does not return immediately and is executing in main thread
// >>>>>how can we make it behave like async_wait???? first
std::cout << __FUNCTION__ << ": Answer: " << answer.get() << "\n";
svc.post([]() { // this adds 1 outstanding work to svc and does not start
auto answer = async_meaning_of_life(true, asio::use_future);
std::cout << __FUNCTION__ << ": Answer: " << answer.get() << "\n";
});
svc.post(using_future);
// this increase outstanding work by 1
// boost::asio::yield_context yield;
// 4-18-2020 this is only used with spawn ,if you want to use stakeful
// coroutines,use push and pull types of coroutine "i wonder how to do
// this???"
// using_yield_ec( yield);this is wrong usage
// using_yield_catch( yield);this is wrong usage
// using_future();this is normal usage but it does not return immediately
// and it executes in main thread.
// using_handler();
svc.post(using_future_composed);
spawn(svc, using_yield_ec);
// this adds 2 outstanding work to svc why 2 works are made while we are
// launching one function????
spawn(svc, using_yield_catch);
// what i think i understand about mechanism of work of spawn:spawn is
// called from main thread>>>>it is just used with coroutines taking
// yield_context as argument,spawn post function to service,spawn makes link
// between the context in which service will be ran"may be main thread or
// new thread AND the context of coroutine function ran in same thread as
// service" or may be the coroutine makes new thread in which it is
// running???".Then when svc.run is called,svc calls task"here svc is caller
// and coroutine is callee",task is executing,yield is called as completion
// token"can we call yield outside initiating function to switch to caller
// "here caller is svc"????. then we are now in svc context which calls
// another task .....
// t.async_wait(&using_future);wrong usage leading to error?why can not in
// use using_future function as completion callback with async_wait???
// spawn(svc, using_future);wrong usage as using_future is not coroutine?
std::thread work([] {
using_future();
using_handler();
auto answer = async_meaning_of_life(true, asio::use_future);
// this function does not return immediately and is executing in main
// thread >>>>>how can we make it behave like async_wait???? first
std::cout << __FUNCTION__ << ": Answer: " << answer.get() << "\n";
});
std::thread work_io([&] { // this starts new thread in which svc is run
svc.run();
});
svc.run(); // this run svc in main thread
// general question:
/*
using_* is considered normal function or coroutine OR composed operation??
async_meaning is considered initiating function?
why does not it return immediately when ran in main thread?how can we make
it return immediately and then when certain result is present ,it calls its
callback??
async_wait is considered initiating function? why does it return
immediately then when timer expires ,it calls back its completion token??
can i make the following composed operation:
i will make composed operation which returns future to caller thread,
and inside it i shall call another composed operation with coroutine,
*/
work.join();
work_io.join();
}
boost::asio::steady_timer t(svc, boost::asio::chrono::seconds(45));
// this function returns immediately and make new thread
No it doesn't create a new thread. It just constructs a service object (the timer) and returns. obviously immediately, like std::string s("hello"); returns when the string is constructed.
t.async_wait(&print);
// this function returns immediately>>>>also it adds 1 out standing work to
// svc. is async_wait body runned in main threaed OR in another thread????if
// it is ran in another thread,how immediate return happens"not
// blocking"??why async_meaning is not returning immediately like
// async_wait?
Slow down.
is async_wait body runned in main threaed OR in another thread?
It's just a function. It runs on the current thread. Like when you called printf.
if it is ran in another thread, how immediate return happens "not
blocking"?
Well, it's not in another thread. But if it were, then it would be obvious how
it would return "not blocking": because the work is not happening on the
current thread.
Why async_meaning_of_life is not returning immediately like
async_wait?
It is returning immediately.
Now, a bit subtler: Even if you use it with a yield_context (inside a
coroutine). It will return immediately and cause the the coroutine to yield.
This means that other tasks get a chance to run on the service thread(s) and
only when the async operation completed, the coroutine will be resumed. From
the point of view of the coroutine, it will have appeared as if the call was
blocking. This is the whole point of (stackful) coroutines. It "abstracts away"
the asynchrony.
So, yes, async_meaning_of_life always (always) returns (almost) immediately.
svc.post([]() { // this adds 1 outstanding work to svc and does not start
Correct. Use a {poll|run}[_one,_for,_until] function to run tasks².
auto answer = async_meaning_of_life(true, asio::use_future);
std::cout << __FUNCTION__ << ": Answer: " << answer.get() << "\n";
You don't ask anything here, but using a future just to await it immediately is
an anti-pattern¹. It's absolutely useless, as it will always generate blocking
behaviour.
You should store the future somewhere, do other work and then when you need the result of the future (and it may or may not have already been completed) you await it (.get() You should store the future somewhere, do other work and then when you need the result of the future (and it may or may not have already been completed) you await it (e.g. by invoking .get()).
// using_yield_ec( yield);this is wrong usage
// using_yield_catch( yield);this is wrong usage
Correct. Used correctly, the Asio service will provide a yield context for you.
// boost::asio::yield_context yield;
// 4-18-2020 this is only used with spawn ,if you want to use stakeful
// coroutines,use push and pull types of coroutine "i wonder how to do
// this???"
No idea. Just refer to the documentation of Boost Coroutine (I suggest Boost Coroutine2). This is off-topic for Asio async operations.
// using_future();this is normal usage but it does not return immediately
// and it executes in main thread.
Well, duh. You took it from a minimal example that ONLY shows the mechanics of the different async_result tokens.
Just refer to a few lines above:
You should store the future somewhere, do other work and then when you need
the result of the future (and it may or may not have already been completed)
you await it (.get() You should store the future somewhere, do other work
and then when you need the result of the future (and it may or may not have
already been completed) you await it (e.g. by invoking .get()).
svc.post(using_future_composed);
Again, I see no questions, but I don't think it means you understand it. I tread.
I see using_future_composed is basically using_future but calling async_meaning_of_life_composed instead.
Now looking at async_meaning_of_life_composed I have no idea what that's supposed to do. It looks like async_meaning_of_life with random lines of code added, doing all kinds of things including blocking operations (see anti-pattern¹) in a function that is supposed to schedule a async operation only.
That's just not what you want to do. Ever.
spawn(svc, using_yield_ec);
// this adds 2 outstanding work to svc why 2 works are made while we are
// launching one function????
Honestly, I do not know. I assume it's because the launch of the coro itself is posted onto the work queue, so it runs exception-safely from one of the worker threads.
The bigger point here is that you still haven't actually started any io-workers, see [²] above.
spawn(svc, using_yield_catch);
// what i think i understand about mechanism of work of spawn:spawn is
// called from main thread>>>>it is just used with coroutines taking
// yield_context as argument,spawn post function to service,spawn makes link
// between the context in which service will be ran"may be main thread or
// new thread AND the context of coroutine function ran in same thread as
// service"...
Erm, basically, yes.
// ... or may be the coroutine makes new thread in which it is
// running???" ...
Definitely not. Both Coroutines and Asio are a device/framework to arrive at concurrency without necessarily multi-threading. Coroutine will never create a thread. Asio will typically not create any threads (unless to implement certain kinds of services on some platforms, but they'd be implementation-details and your tasks/handlers will never run on such a hidden thread).
// ... .Then when svc.run is called,svc calls task"here svc is caller
// and coroutine is callee",task is executing,yield is called as completion
// token"can we call yield outside initiating function to switch to caller
// "here caller is svc"????. then we are now in svc context which calls
// another task .....
Huh. No, yield_context is not a portal to a different time-space continuum.
I'm not very sure what you mean with `'call yield' so when you are thinking about calling it from outside the initiating function, I'd say: probably don't do that.
// t.async_wait(&using_future);wrong usage leading to error?why can not in
// use using_future function as completion callback with async_wait???
Because it doesn't satisfy the handler requirements for steady_time::async_wait (which should take a boost::system::error_code only. Did you perhaps mean use_future (from Asio) instead of your own using_future?
auto ignored_future = t.async_wait(boost::asio::use_future);
I admit the names are somewhat confusing. If it helps, rename all the using_XYZ functions to demonstration_using_XYZ.
// spawn(svc, using_future);wrong usage as using_future is not coroutine?
You got that right.
std::thread work([]
using_future();
using_handler();
auto answer = async_meaning_of_life(true, asio::use_future);
// this function does not return immediately and is executing in main
// thread >>>>>how can we make it behave like async_wait???? first
std::cout << __FUNCTION__ << ": Answer: " << answer.get() << "\n";
});
I believe you just copy/pasted the comment, but in case you really worried: no that is not run on the main thread. It's run on the work thread, and yes, that's because you block on the future::get(). See above¹.
std::thread work_io([&] { // this starts new thread in which svc is run
svc.run();
});
Better late than never :)
svc.run(); // this run svc in main thread
Correct, and running more doesn't hurt. Running the service on multiple threads may require handler synchronization: Why do I need strand per connection when using boost::asio?
// general question:
/*
using_* is considered normal function or coroutine OR composed operation??
Normal functions (see the clarification about renaming it to demonstration_using_XYZ above)
async_meaning is considered initiating function?
Correct.
why does not it return immediately when ran in main thread?
It does. See above. If you mean, why does your own function async_meaning_of_life_composed bblock? That's because you made it do blocking operations (see above).
how can we make
it return immediately and then when certain result is present ,it calls its
callback??
The usual way to do to it, is by launching other async operations. Say, for example, you wait for network operation to complete (asynchronously, e.g. using boost::asio::async_write) and when it's done, you invoke the handler. The async_result helper makes it so you don't have to know the actual completion_handler_type, and it will "magically" do the right thing regardless of how your initiating function was invoked.
async_wait is considered initiating function? why does it return
immediately then when timer expires ,it calls back its completion token??
Because that's how async operations are designed. They were designed that way because that is useful behaviour.
can i make the following composed operation:
i will make composed operation which returns future to caller thread,
and inside it i shall call another composed operation with coroutine,
*/
You are free to start a coroutine. Just make sure you transfer ownership of the async_result result so you can invoke the handler from there, to signal completion of your operation.
In the case of futures, the usual way to compose operations is by composing futures, like: https://www.boost.org/doc/libs/1_72_0/doc/html/thread/synchronization.html#thread.synchronization.futures.then
std::string someotheroperation(int);
future<int> fut1 = foo();
future<std::string> fut2 = foo().then(someotheroperation);
BONUS
The ultimate piece of documentation on writing Composed Operations with Asio is (ironically) this page in the Beast documentation. Perhaps seeing some more real-life examples may give you more ideas.
Keep in mind Beast comes with a few facilities that make library maintenance for /them/ a bit easier, but could well be overkill for your own application. Then again, if you err on theur path you will not overlook important things like the one we discussed here earlier:

RVO and Move Semantics in Objective-C++

TL;DR: Does the __block attribute on an std::vector prevent RVO in Objective-C++?
In Modern C++, the canonical way to return a vector from a function is to just return it by value so that return value optimization can be used if possible. In Objective-C++, this appears to work the same way.
- (void)fetchPeople {
std::vector<Person> people = [self readPeopleFromDatabase];
}
- (std::vector<Person>)readPeopleFromDatabase {
std::vector<Person> people;
people.emplace_back(...);
people.emplace_back(...);
// No copy is made here.
return people;
}
However, if the __block attribute is applied to the second vector, then it appears that a copy of the vector is being created when it returns. Here is a slightly contrived example:
- (std::vector<Person>)readPeopleFromDatabase {
// __block is needed to allow the vector to be modified.
__block std::vector<Person> people;
void (^block)() = ^ {
people.emplace_back(...);
people.emplace_back(...);
};
block();
#if 1
// This appears to require a copy.
return people;
#else
// This does not require a copy.
return std::move(people);
#endif
}
There are plenty of Stack Overflow questions that explicitly state that you don't need to use std::move when returning a vector because that will prevent copy elision from taking place.
However, this Stack Overflow question states that there are, indeed, some times when you do need to explicitly use std::move when copy elision is not possible.
Is the use of __block in Objective-C++ one of those times when copy elision is not possible and std::move should be used instead? My profiling appears to confirm that, but I'd love a more authoritative explanation.
(This is on Xcode 10 with C++17 support.)
I don't know about authoritative, but a __block variable is specifically designed to be able to outlive the scope it's in and contains special runtime state that tracks whether it's stack- or heap-backed. For example:
#include <iostream>
#include <dispatch/dispatch.h>
using std::cerr; using std::endl;
struct destruct_logger
{
destruct_logger()
{}
destruct_logger(const destruct_logger& rhs)
{
cerr << "destruct_logger copy constructor: " << &rhs << " --> " << this << endl;
}
void dummy() {}
~destruct_logger()
{
cerr << "~destruct_logger on " << this << endl;
}
};
void my_function()
{
__block destruct_logger logger;
cerr << "Calling dispatch_after, &logger = " << &logger << endl;
dispatch_after(
dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(),
^{
cerr << "Block firing\n";
logger.dummy();
});
cerr << "dispatch_after returned: &logger = " << &logger << endl;
}
int main(int argc, const char * argv[])
{
my_function();
cerr << "my_function() returned\n";
dispatch_main();
return 0;
}
If I run that code, I get the following output:
Calling dispatch_after, &logger = 0x7fff5fbff718
destruct_logger copy constructor: 0x7fff5fbff718 --> 0x100504700
dispatch_after returned: &logger = 0x100504700
~destruct_logger on 0x7fff5fbff718
my_function() returned
Block firing
~destruct_logger on 0x100504700
There's quite a lot happening here:
Before we call dispatch_after, logger is still stack-based. (0x7fff… address)
dispatch_after internally performs a Block_copy() of the block which captures logger. This means the logger variable must now be moved to the heap. As it's a C++ object, this means the copy constructor is invoked.
And indeed, after dispatch_after returns, &logger now evaluates to the new (heap) address.
The original stack instance of course must be destroyed.
The heap instance is only destroyed once the capturing block has been destroyed.
So a __block "variable" is actually a much more complex object that can move around in memory on demand behind the scenes.
If you were to subsequently return logger from my_function, RVO wouldn't be possible, because (a) it now lives on the heap, not the stack, and (b) not making a copy on returning would allow mutation of the instance captured by blocks.
I guess it might be possible to make it runtime state dependent - use RVO memory for stack-backing, then if it gets moved to the heap, copy back into the return value when the function returns. But this would complicate functions that operate on blocks, as the backing state would now need to be stored separately from the variable. It also seems like overly complex and surprising behaviour, so I'm not surprised that RVO doesn't happen for __block variables.

How to force a libusb event so that libusb_handle_events() returns

Suppose I have a libusb program that just uses the hotplug API. You register a callback and then apparently have to call libusb_handle_events() in a loop which then calls your hotplug callback.
int LIBUSB_CALL hotplugCallback(libusb_context* ctx,
libusb_device* device,
libusb_hotplug_event event,
void* user_data)
{
cout << "Device plugged in or unplugged";
}
void main()
{
libusb_init(nullptr);
libusb_hotplug_register_callback(nullptr,
static_cast<libusb_hotplug_event>(LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED | LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT),
LIBUSB_HOTPLUG_NO_FLAGS,
LIBUSB_HOTPLUG_MATCH_ANY,
LIBUSB_HOTPLUG_MATCH_ANY,
LIBUSB_HOTPLUG_MATCH_ANY,
&hotplugCallback,
this,
&hotplugCallbackHandle);
for (;;)
{
if (libusb_handle_events_completed(nullptr, nullptr) != LIBUSB_SUCCESS)
return 1;
}
return 0;
}
The question is, without timeout hacks how can I exit this event loop cleanly? I can't find any functions that force libusb_handle_events() (or libusb_handle_events_completed()) to return. In theory they could just never return.
Sorry if this is late.
The question could have been phrased better but I'm assuming (from your comment updates) that your actual program resembles something a little closer to this:
int LIBUSB_CALL hotplugCallback(libusb_context *ctx,
libusb_device *device,
libusb_hotplug_event event,
void *user_data) {
cout << "Device plugged in or unplugged";
}
void SomeClass::someFunction() {
libusb_init(nullptr);
libusb_hotplug_register_callback(nullptr,
static_cast<libusb_hotplug_event>(LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED | LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT),
LIBUSB_HOTPLUG_NO_FLAGS,
LIBUSB_HOTPLUG_MATCH_ANY,
LIBUSB_HOTPLUG_MATCH_ANY,
LIBUSB_HOTPLUG_MATCH_ANY,
&hotplugCallback,
this,
&hotplugCallbackHandle);
this->thread = std::thread([this]() {
while (this->handlingEvents) {
int error = libusb_handle_events_completed(context, nullptr);
}
});
}
Let's say your object is being deallocated and, no matter what is happening on the USB bus, you don't care and you want to clean up your thread.
You negate this->handlingEvents and you call thread.join() and the thread hangs for 60 seconds and then execution resumes.
This is done because the default behavior of libusb_handle_events_completed calls libusb_handle_events_timeout_completed and passes in a 60 second timeout interval with plans to make it infinite.
The way you force libusb_handle_events_completed to return is you call libusb_hotplug_deregister_callback which wakes up libusb_handle_events(), causing the function to return.
There is more info about this behavior in the docs.
So your destructor (or wherever you want to stop listening immediately) for the class could look something like this:
SomeClass::~SomeClass() {
this->handlingEvents = false;
libusb_hotplug_deregister_callback(context, hotplugCallbackHandle);
if (this->thread.joinable()) this->thread.join();
libusb_exit(this->context);
}
In the function:
int libusb_handle_events_completed(libusb_context* ctx, int* completed)
You can change the value of the completed to "1" so the function will return without blocking
According to their docs:
If the parameter completed is not NULL then after obtaining the event
handling lock this function will return immediately if the integer
pointed to is not 0. This allows for race free waiting for the
completion of a specific transfer.
There is no functions in libusb that force libusb_handle_events() to return.
It's recommended to use libusb_handle_events() in a dedicated thread so your main thread will not be blocked by this call. Even though, if you need to manipulate the call of the event handler you can put the call in a while(condition) and change the condition state in your main thread.
Libusb documentation details this here.

issues about using async_write right after async_read_until

My code is as follows:
boost::asio::streambuf b1;
boost::asio::async_read_until(upstream_socket_, b1, '#',
boost::bind(&bridge::handle_upstream_read, shared_from_this(),
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
void handle_upstream1_read(const boost::system::error_code& error,
const size_t& bytes_transferred)
{
if (!error)
{
async_write(downstream_socket_,
b2,
boost::bind(&bridge::handle_downstream_write,
shared_from_this(),
boost::asio::placeholders::error));
}
else
close();
}
According to the documentation of async_read_until, http://www.boost.org/doc/libs/1_55_0/doc/html/boost_asio/reference/async_read_until/overload1.html,
After a successful async_read_until operation, the streambuf may contain additional data beyond the delimiter. An application will typically leave that data in the streambuf for a subsequent async_read_until operation to examine.
I know that the streambuf may contain additional data beyond the delimiter, but, in my case, will it write those additional data (the data beyond the char'#') to the downstream_socket_ inside the async_write operation? Or will async_write function be smart enough not to write those additional data until the next time the handle_upstream1_read function is being called?
According to the approaches in the documentation, the data in streambuf are stored in the istream first ( std::istream response_stream(&streambuf); )
and then put it into a string by using std::getline() funciton.
Do I really need to store the streambuf in istream first and then convert it into a string and then convert it back to char arrary (so that I can send the char array to the downstream_socket_ ) instead of just using the async_write to write the data( up to but not including the delimter, '#' ) to the downstream_socket_ ?
I prefer the second approach so that I don't need to make several conversion on the data. However, it seems that something is wrong when I tried the second approach.
My ideal case is that:
upstream_socket_ received xxxx#yyyy by using async_read_until
xxxx# is written to the downstream_socket_
upstream_socket_ received zzzz#kkkk by using async_read_until
yyyyzzzz# is written to the downstream_socket_
It seems that async_write operation still writes the data beyond the delimiter to the downstream_socket_. (but I am not 100% sure about this)
I appreciate if anyone can provide a little help !
The async_write() overload being used is considered complete when all of the streambuf's data, its input sequence, has been written to the WriteStream (socket). It is equivalent to calling:
boost::asio::async_write(stream, streambuf,
boost::asio::transfer_all(), handler);
One can limit the amount of bytes written and consumed from the streambuf object by calling this async_write() overload with the boost::asio::transfer_exactly completion condition:
boost::asio::async_write(stream, streambuf,
boost::asio::transfer_exactly(n), handler);
Alternatively, one can write directly from the streambuf's input sequence. However, one will need to explicitly consume from the streambuf.
boost::asio::async_write(stream,
boost::asio::buffer(streambuf.data(), n), handler);
// Within the completion handler...
streambuf.consume(n);
Note that when the async_read_until() operation completes, the completion handler's bytes_transferred argument contains the number of bytes in the streambuf's input sequence up to and including the delimiter, or 0 if an error occurred.
Here is a complete example demonstrating using both approaches. The example is written using synchronous operations in an attempt to simplify the flow:
#include <iostream>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
// This example is not interested in the handlers, so provide a noop function
// that will be passed to bind to meet the handler concept requirements.
void noop() {}
/// #brief Helper function that extracts a string from a streambuf.
std::string make_string(
boost::asio::streambuf& streambuf,
std::size_t n)
{
return std::string(
boost::asio::buffers_begin(streambuf.data()),
boost::asio::buffers_begin(streambuf.data()) + n);
}
int main()
{
using boost::asio::ip::tcp;
boost::asio::io_service io_service;
// Create all I/O objects.
tcp::acceptor acceptor(io_service, tcp::endpoint(tcp::v4(), 0));
tcp::socket server_socket(io_service);
tcp::socket client_socket(io_service);
// Connect client and server sockets.
acceptor.async_accept(server_socket, boost::bind(&noop));
client_socket.async_connect(acceptor.local_endpoint(), boost::bind(&noop));
io_service.run();
// Mockup write_buffer as if it read "xxxx#yyyy" with read_until()
// using '#' as a delimiter.
boost::asio::streambuf write_buffer;
std::ostream output(&write_buffer);
output << "xxxx#yyyy";
assert(write_buffer.size() == 9);
auto bytes_transferred = 5;
// Write to server.
boost::asio::write(server_socket, write_buffer,
boost::asio::transfer_exactly(bytes_transferred));
// Verify write operation consumed part of the input sequence.
assert(write_buffer.size() == 4);
// Read from client.
boost::asio::streambuf read_buffer;
bytes_transferred = boost::asio::read(
client_socket, read_buffer.prepare(bytes_transferred));
read_buffer.commit(bytes_transferred);
// Copy from the read buffers input sequence.
std::cout << "Read: " <<
make_string(read_buffer, bytes_transferred) << std::endl;
read_buffer.consume(bytes_transferred);
// Mockup write_buffer as if it read "zzzz#kkkk" with read_until()
// using '#' as a delimiter.
output << "zzzz#kkkk";
assert(write_buffer.size() == 13);
bytes_transferred = 9; // yyyyzzzz#
// Write to server.
boost::asio::write(server_socket, buffer(write_buffer.data(),
bytes_transferred));
// Verify write operation did not consume the input sequence.
assert(write_buffer.size() == 13);
write_buffer.consume(bytes_transferred);
// Read from client.
bytes_transferred = boost::asio::read(
client_socket, read_buffer.prepare(bytes_transferred));
read_buffer.commit(bytes_transferred);
// Copy from the read buffers input sequence.
std::cout << "Read: " <<
make_string(read_buffer, bytes_transferred) << std::endl;
read_buffer.consume(bytes_transferred);
}
Output:
Read: xxxx#
Read: yyyyzzzz#
A few other notes:
The streambuf owns the memory, and std::istream and std::ostream use the memory. Using streams may be a good idea when one needs to extract formatted input or insert formatted output. For instance, when one wishes to read the string "123" as an integer 123.
One can directly access the streambuf's input sequence and iterate over it. In the example above, I use boost::asio::buffers_begin() to help construct a std::string by iterating over a streambuf's input sequence.
std::string(
boost::asio::buffers_begin(streambuf.data()),
boost::asio::buffers_begin(streambuf.data()) + n);
A stream-based transport protocol is being used, so handle incoming data as a stream. Be aware that even if the intermediary server reframes messages and sends "xxxx#" in one write operation and "yyyyzzzz#" in a subsequent write operation, the downstream may read "xxxx#yyyy" in a single read operation.

Complex check-methods with boost.test

I want to test different constructors of a string class. Therefore I wrote myself a test method that checks a couple standard things:
void checkStringStandards(String& s, size_t length, const char* text){
BOOST_CHECK_EQUAL(s.length(), length);
...
}
Then I added a test method
BOOST_AUTO_TEST_CASE(String_construct){
String s1;
checkStringStandards(s1, 0, "");
String s2("normal char");
checkStringStandards(s2, 11, "normal char");
}
The problem is, that when it fails, I only get the line- and file information from within checkStringStandards ! I can't know by the output whether the first or the second call caused this.
What's the common fix for that?
Cheers!
The solution to this problem is to write a custom predicate that performs the checks and use BOOST_REQUIRE(custom_predicate(args)) in the different test cases. A custom predicate can take any arguments you want and returns boost::test_tools::predicate_result, a type that is compatible with the assertion macros in Boost.Test into which you can build up a detailed diagnostic message during failure.
To use your example:
using namespace boost::test_tools;
predicate_result checkStringStandards(String& s, size_t length, const char* text) {
predicate_result result{true};
if (s.length() != length) {
result = false;
result.message() << "\nString " << s
<< " differs in length; expected: "
<< length << ", actual: " << s.length();
}
...
return result;
}
BOOST_AUTO_TEST_CASE(String_construct){
String s1;
BOOST_REQUIRE(checkStringStandards(s1, 0, ""));
String s2("normal char");
BOOST_REQUIRE(checkStringStandards(s2, 11, "normal char"));
}
The curious \n at the beginning of the message is so that when the diagnostic is printed, the text with "String ... differs in length" will be emitted on it's own line. If the predicate fails, it bubbles its failure up to BOOST_REQUIRE which will trigger the test failure and report the failure at the line invoking BOOST_REQUIRE instead of inside your custom predicate.
There is another yuckier alternative that also achieves the same result by making your custom assertions as gigantic megamacros, but I find that so horrid I'm not even going to show an example of how to do it :).
there is no common fix for that. these BOOST_CHECK_... macros exist by intention to avoid function calls where the line number gets lost (unless explicitely passed as param).
you can get round this problem by looping through the parameter set inside your test case.