When receiving data on wire and sending it to upper applications, normally, in C style, we have a struct for example with a void*:
struct SData{
//... len, size, version, msg type, ...
void* payload;
}
Later in the code, after error checking and mallocating, ..., we can do something as:
if(msgType == type1){
struct SType1* ptr = (struct SType1*) SData->payload;
}
In C++, an attempt to use unique_ptr fails in the following snippet:
struct SData{
// .. len, size, version, msg type, ...
std::unique_ptr<void> payload;
}
But as you know, this will cause:
error: static assertion failed: can't delete pointer to incomplete type
Is there a way to use smart pointers to handle this?
One solution I found is here:
Should std::unique_ptr<void> be permitted
Which requires creating a custom deleter:
void HandleDeleter(HANDLE h)
{
if (h) CloseHandle(h);
}
using
UniHandle = unique_ptr<void, function<void(HANDLE)>>;
This will require significantly more additional code (compared to the simple unsafe C Style), since for each type of payload there has to be some logic added.
This will require significantly more additional code (compared to the simple unsafe C Style), since for each type of payload there has to be some logic added.
The additional complexity is only calling the added destructors. You could use a function pointer instead of std::function since no closure state should ever be used.
If you don't want destructors, but only to add RAII to the C idiom, then use a custom deleter which simply does operator delete or std::free.
Related
Reference:
boost_1_78_0/doc/html/boost_asio/reference/ip__basic_resolver/async_resolve/overload1.html
template<
typename ResolveHandler = DEFAULT>
DEDUCED async_resolve(
const query & q,
ResolveHandler && handler = DEFAULT);
The handler to be called when the resolve operation completes. Copies
will be made of the handler as required. The function signature of the
handler must be:
void handler(
const boost::system::error_code& error, // Result of operation.
resolver::results_type results // Resolved endpoints as a range.
);
boost_1_78_0/libs/beast/example/websocket/client/async-ssl/websocket_client_async_ssl.cpp
void run(char const *host, char const *port, char const *text) {
...
resolver_.async_resolve(
host, port,
beast::bind_front_handler(&session::on_resolve, shared_from_this()));
}
void on_resolve(beast::error_code ec, tcp::resolver::results_type results) {
if (ec)
return fail(ec, "resolve");
// Set a timeout on the operation
beast::get_lowest_layer(ws_).expires_after(std::chrono::seconds(30));
// Make the connection on the IP address we get from a lookup
beast::get_lowest_layer(ws_).async_connect(
results,
beast::bind_front_handler(&session::on_connect, shared_from_this()));
}
Question 1> Why does the on_resolve use the following function signature?
on_resolve(beast::error_code ec, tcp::resolver::results_type results)
As shown above, the first parameter(i.e. ec) is taken as pass-by value. This happens almost in all other functions which take a beast::error_code as an input parameter within sample code.
Instead of
on_resolve(const beast::error_code& ec, tcp::resolver::results_type results)
Question 2> Why doesn't the documentation suggest using the following instead?
on_resolve(const beast::error_code& ec, const tcp::resolver::results_type& results)
Thank you
It's a cultural difference between Asio and Beast if you will.
UPDATE
There's some contention about my initial response.
It turns out that at least Boost System's error_code recently got endowed with shiny new (non-standard) features, that makes it bigger. Perhaps big enough to make it more efficient to pass by reference.
In the words of Vinnie Falco: This needs to be studied again.
Rationale
In Asio, the standard "doctrine" is to take error_code by const&. In Beast, the standard practice is actually to pass by value, which is, IMO, how error_code is intended.
In essence, error_code is just a tuple of (int, error_category const*) which is trivially copied and therefore optimized. Passing by value allows compilers much more room for optimization, especially when inlining. A key factor is that value-arguments never create aliasing opportunities.
(I can try to find a reference as I think some Beast devs are on record explaining this rationale.)
Why is it OK?
Any function that takes T by value is delegation-compatible with the requirement that it takes T by const reference, as long as T is copyable.
Other thoughts
There may have been historical reasons why Asio preferred, or even mandated error_code const& in the past, but as far as I am aware, any of these reasons are obsolete.
Ok, muddling though Stack on the particulars about void*, books like The C Programming Language (K&R) and The C++ Programming Language (Stroustrup). What have I learned? That void* is a generic pointer with no type inferred. It requires a cast to any defined type and printing void* just yields the address.
What else do I know? void* can't be dereferenced and thus far remains the one item in C/C++ from which I have discovered much written about but little understanding imparted.
I understand that it must be cast such as *(char*)void* but what makes no sense to me for a generic pointer is that I must somehow already know what type I need in order to grab a value. I'm a Java programmer; I understand generic types but this is something I struggle with.
So I wrote some code
typedef struct node
{
void* data;
node* link;
}Node;
typedef struct list
{
Node* head;
}List;
Node* add_new(void* data, Node* link);
void show(Node* head);
Node* add_new(void* data, Node* link)
{
Node* newNode = new Node();
newNode->data = data;
newNode->link = link;
return newNode;
}
void show(Node* head)
{
while (head != nullptr)
{
std::cout << head->data;
head = head->link;
}
}
int main()
{
List list;
list.head = nullptr;
list.head = add_new("My Name", list.head);
list.head = add_new("Your Name", list.head);
list.head = add_new("Our Name", list.head);
show(list.head);
fgetc(stdin);
return 0;
}
I'll handle the memory deallocation later. Assuming I have no understanding of the type stored in void*, how do I get the value out? This implies I already need to know the type, and this reveals nothing about the generic nature of void* while I follow what is here although still no understanding.
Why am I expecting void* to cooperate and the compiler to automatically cast out the type that is hidden internally in some register on the heap or stack?
I'll handle the memory deallocation later. Assuming I have no understanding of the type stored in void*, how do I get the value out?
You can't. You must know the valid types that the pointer can be cast to before you can dereference it.
Here are couple of options for using a generic type:
If you are able to use a C++17 compiler, you may use std::any.
If you are able to use the boost libraries, you may use boost::any.
Unlike Java, you are working with memory pointers in C/C++. There is no encapsulation whatsoever. The void * type means the variable is an address in memory. Anything can be stored there. With a type like int * you tell the compiler what you are referring to. Besides the compiler knows the size of the type (say 4 bytes for int) and the address will be a multiple of 4 in that case (granularity/memory alignment). On top, if you give the compiler the type it will perform consistency checks at compilation time. Not after. This is not happening with void *.
In a nutshell, you are working bare metal. The types are compiler directives and do not hold runtime information. Nor does it track the objects you are dynamically creating. It is merely a segment in memory that is allocated where you can eventually store anything.
The main reason to use void* is that different things may be pointed at. Thus, I may pass in an int* or Node* or anything else. But unless you know either the type or the length, you can't do anything with it.
But if you know the length, you can handle the memory pointed at without knowing the type. Casting it as a char* is used because it is a single byte, so if I have a void* and a number of bytes, I can copy the memory somewhere else, or zero it out.
Additionally, if it is a pointer to a class, but you don't know if it is a parent or inherited class, you may be able to assume one and find out a flag inside the data which tells you which one. But no matter what, when you want to do much beyond passing it to another function, you need to cast it as something. char* is just the easiest single byte value to use.
Your confusion derived from habit to deal with Java programs. Java code is set of instruction for a virtual machine, where function of RAM is given to a sort of database, which stores name, type, size and data of each object. Programming language you're learning now is meant to be compiled into instruction for CPU, with same organization of memory as underlying OS have. Existing model used by C and C++ languages is some abstract built on top of most of popular OSes in way that code would work effectively after being compiled for that platform and OS. Naturally that organization doesn't involve string data about type, except for famous RTTI in C++.
For your case RTTI cannot be used directly, unless you would create a wrapper around your naked pointer, which would store the data.
In fact C++ library contains a vast collection of container class templates that are useable and portable, if they are defined by ISO standard. 3/4 of standard is just description of library often referred as STL. Use of them is preferable over working with naked pointers, unless you mean to create own container for some reason. For particular task only C++17 standard offered std::any class, previously present in boost library. Naturally, it is possible to reimplement it, or, in some cases, to replace by std::variant.
Assuming I have no understanding of the type stored in void*, how do I get the value out
You don't.
What you can do is record the type stored in the void*.
In c, void* is used to pass around a binary chunk of data that points at something through one layer of abstraction, and recieve it at the other end, casting it back to the type that the code knows it will be passed.
void do_callback( void(*pfun)(void*), void* pdata ) {
pfun(pdata);
}
void print_int( void* pint ) {
printf( "%d", *(int*)pint );
}
int main() {
int x = 7;
do_callback( print_int, &x );
}
here, we forget thet ype of &x, pass it through do_callback.
It is later passed to code inside do_callback or elsewhere that knows that the void* is actually an int*. So it casts it back and uses it as an int.
The void* and the consumer void(*)(void*) are coupled. The above code is "provably correct", but the proof does not lie in the type system; instead, it depends on the fact we only use that void* in a context that knows it is an int*.
In C++ you can use void* similarly. But you can also get fancy.
Suppose you want a pointer to anything printable. Something is printable if it can be << to a std::ostream.
struct printable {
void const* ptr = 0;
void(*print_f)(std::ostream&, void const*) = 0;
printable() {}
printable(printable&&)=default;
printable(printable const&)=default;
printable& operator=(printable&&)=default;
printable& operator=(printable const&)=default;
template<class T,std::size_t N>
printable( T(&t)[N] ):
ptr( t ),
print_f( []( std::ostream& os, void const* pt) {
T* ptr = (T*)pt;
for (std::size_t i = 0; i < N; ++i)
os << ptr[i];
})
{}
template<std::size_t N>
printable( char(&t)[N] ):
ptr( t ),
print_f( []( std::ostream& os, void const* pt) {
os << (char const*)pt;
})
{}
template<class T,
std::enable_if_t<!std::is_same<std::decay_t<T>, printable>{}, int> =0
>
printable( T&& t ):
ptr( std::addressof(t) ),
print_f( []( std::ostream& os, void const* pt) {
os << *(std::remove_reference_t<T>*)pt;
})
{}
friend
std::ostream& operator<<( std::ostream& os, printable self ) {
self.print_f( os, self.ptr );
return os;
}
explicit operator bool()const{ return print_f; }
};
what I just did is a technique called "type erasure" in C++ (vaguely similar to Java type erasure).
void send_to_log( printable p ) {
std::cerr << p;
}
Live example.
Here we created an ad-hoc "virtual" interface to the concept of printing on a type.
The type need not support any actual interface (no binary layout requirements), it just has to support a certain syntax.
We create our own virtual dispatch table system for an arbitrary type.
This is used in the C++ standard library. In c++11 there is std::function<Signature>, and in c++17 there is std::any.
std::any is void* that knows how to destroy and copy its contents, and if you know the type you can cast it back to the original type. You can also query it and ask it if it a specific type.
Mixing std::any with the above type-erasure techinque lets you create regular types (that behave like values, not references) with arbitrary duck-typed interfaces.
I'm still learning C++, and I'm doing some API work, but I'm, having trouble parsing this pointer arrangement.
void* data;
res = npt.receive(0x1007, params, 1, response, (void**)&data, size);
uint32_t* op = (uint32_t*)data;
uint32_t num = *op;
op++;
Can anyone explain what is going on with that void pointer? I see it being defined, it does something in the res line(maybe initialized?), then it's copied to an uint32 pointer, and dereferenced in num. Can anyone help me parse the (void**)&data declaration?
Pay attention when you use the void pointer:
The void type of pointer is a special type of pointer. In C++, void represents the absence of type. Therefore, void pointers are pointers that point to a value that has no type (and thus also an undetermined length and undetermined dereferencing properties).
This gives void pointers a great flexibility, by being able to point to any data type, from an integer value or a float to a string of characters. In exchange, they have a great limitation: the data pointed to by them cannot be directly dereferenced (which is logical, since we have no type to dereference to), and for that reason, any address in a void pointer needs to be transformed into some other pointer type that points to a concrete data type before being dereferenced.
From C++ reference
Firstly: What is npt?
Secondly: Guessing what npt could be some explanation:
// Declare a pointer to void named data
void* data;
// npt.receive takes as 5th parameter a pointer to pointer to void,
// which is why you provide the address of the void* using &data.
// The void ** appears to be unnecessary unless the data type of the
// param is not void **
// What is "npt"?
res = npt.receive(0x1007, params, 1, response, (void**)&data, size);
// ~.receive initialized data with contents.
// Now make the uint32_t data usable by casting void * to uint32_t*
uint32_t* op = (uint32_t*)data;
// Use the data by dereferencing it.
uint32_t num = *op;
// Pointer arithmetic: Move the pointer by sizeof(uint32_t).
// Did receive fill in an array?
op++;
Update
Signature of receive is:
<whatever return type> receive(uint16_t code, uint32_t* params, uint8_t nparam, Container& response, void** data, uint32_t& size)
So the data parameter is of type void** already so the explicit type cast to void** using (void**) is not necessary.
Considering the usage, the received data appears to be an array of uint32_t values IN THIS CASE!
Void as a type means no type and no type information regarding size and alignment is available, but is mandatory for lexical and syntactical consistency.
In conjunction with the *, it can be used as a pointer to data of unknown type and must be explicitly cast to another type (adds type information) before any use.
You usually have a void* or void** in an API, if you dont know the specific data type or only received plain byte data.
To understand this please read up C type erasure using void*
Please read up as basics before:
Dynamically allocated C arrays.
Pointers and Pointer Arithmetics.
From the code, ntp.receive tells you whether it receives anything successfully in the return code but it also needs to give you what it receives. It has a pointer that it wants to pass back, so you have to tell it where that pointer is so that it can fill it, hence (void **), a pointer to a pointer, being the address of your pointer, &data.
When you have received it, you know as the developer that what it points to is actually a uint_32 value so you copy the void pointer into one that points to a uint_32. In fact, this step is unnecessary since you could have cast the uint_32 pointer to void** in the above call but we'll let that slide.
Now that you have told the compiler that the pointer points to a 32 bit number, you can take the number on the other end of that pointer (*op) and store it in a local variable. Again, unnecessary, as *op could be used anywhere num is subsequently used.
Hope this helps.
I am trying to get more familiar with the C++11 standard by implementing the std::iterator on my own doubly linked list collection and also trying to make my own sort function to sort it.
I would like the sort function to accept a lamba as a way of sorting by making the sort accept a std::function, but it does not compile (I do not know how to implement the move_iterator, hence returning a copy of the collection instead of modifying the passed one).
template <typename _Ty, typename _By>
LinkedList<_Ty> sort(const LinkedList<_Ty>& source, std::function<bool(_By, _By)> pred)
{
LinkedList<_Ty> tmp;
while (tmp.size() != source.size())
{
_Ty suitable;
for (auto& i : source) {
if (pred(suitable, i) == true) {
suitable = i;
}
}
tmp.push_back(suitable);
}
return tmp;
}
Is my definition of the function wrong? If I try to call the function, I recieve a compilation error.
LinkedList<std::string> strings{
"one",
"two",
"long string",
"the longest of them all"
};
auto sortedByLength = sort(strings, [](const std::string& a, const std::string& b){
return a.length() < b.length();
});
Error: no instance of function template "sort" matches the argument
list argument types are: (LinkedList, lambda []bool
(const std::string &a, const std::string &)->bool)
Additional info, the compilation also gives the following error:
Error 1 error C2784: 'LinkedList<_Ty> sort(const
LinkedList<_Ty> &,std::function)' : could not
deduce template argument for 'std::function<bool(_By,_By)>'
Update: I know the sorting algorithm is incorrect and would not do what is wanted, I have no intention in leaving it as is and do not have a problem fixing that, once the declaration is correct.
The problem is that _By used inside std::function like this cannot be deduced from a lambda closure. You'd need to pass in an actual std::function object, and not a lambda. Remember that the type of a lambda expression is an unnamed class type (called the closure type), and not std::function.
What you're doing is a bit like this:
template <class T>
void foo(std::unique_ptr<T> p);
foo(nullptr);
Here, too, there's no way to deduce T from the argument.
How the standard library normally solves this: it does not restrict itself to std::function in any way, and simply makes the type of the predicate its template parameter:
template <typename _Ty, typename _Pred>
LinkedList<_Ty> sort(const LinkedList<_Ty>& source, _Pred pred)
This way, the closure type will be deduced and all is well.
Notice that you don't need std::function at all—that's pretty much only needed if you need to store a functor, or pass it through a runtime interface (not a compiletime one like templates).
Side note: your code is using identifiers which are reserved for the compiler and standard library (identifiers starting with an underscore followed by an uppercase letter). This is not legal in C++, you should avoid such reserved identifiers in your code.
The regular std::vector has emplace_back which avoid an unnecessary copy. Is there a reason spsc_queue doesn't support this? Is it impossible to do emplace with lock-free queues for some reason?
I'm not a boost library implementer nor maintainer, so the rationale behind why not to include an emplace member function is beyond my knowledge, but it isn't too difficult to implement it yourself if you really need it.
The spsc_queue has a base class of either compile_time_sized_ringbuffer or runtime_sized_ringbuffer depending on if the size of the queue is known at compilation or not. These two classes maintain the actual buffer used with the obvious differences between a dynamic buffer and compile-time buffer, but delegate, in this case, their push member functions to a common base class - ringbuffer_base.
The ringbuffer_base::push function is relatively easy to grok:
bool push(T const & t, T * buffer, size_t max_size)
{
const size_t write_index = write_index_.load(memory_order_relaxed); // only written from push thread
const size_t next = next_index(write_index, max_size);
if (next == read_index_.load(memory_order_acquire))
return false; /* ringbuffer is full */
new (buffer + write_index) T(t); // copy-construct
write_index_.store(next, memory_order_release);
return true;
}
An index into the location where the next item should be stored is done with a relaxed load (which is safe since the intended use of this class is single producer for the push calls) and gets the appropriate next index, checks to make sure everything is in-bounds (with a load-acquire for appropriate synchronization with the thread that calls pop) , but the main statement we're interested in is:
new (buffer + write_index) T(t); // copy-construct
Which performs a placement new copy construction into the buffer. There's nothing inherently thread-unsafe about passing around some parameters to use to construct a T directly from viable constructor arguments. I wrote the following snippet and made the necessary changes throughout the derived classes to appropriately delegate the work up to the base class:
template<typename ... Args>
std::enable_if_t<std::is_constructible<T,Args...>::value,bool>
emplace( T * buffer, size_t max_size,Args&&... args)
{
const size_t write_index = write_index_.load(memory_order_relaxed); // only written from push thread
const size_t next = next_index(write_index, max_size);
if (next == read_index_.load(memory_order_acquire))
return false; /* ringbuffer is full */
new (buffer + write_index) T(std::forward<Args>(args)...); // emplace
write_index_.store(next, memory_order_release);
return true;
}
Perhaps the only difference is making sure that the arguments passed in Args... can actually be used to construct a T, and of course doing the emplacement via std::forward instead of a copy construction.