How to design smart pointer of array type in C++11 - c++11

This is a class which contains image data.
class MyMat
{
public:
int width, height, format;
uint8_t *data;
}
I want to design MyMat with automatic memory management. The image data could be shared among many objects.
Common APIs which I'm going to design:
+) C++ 11
+) Assignment : share data
MyMat a2(w, h, fmt);
.................
a2 = a1;
+) Accessing data should be simple and short.
Can use raw pointer directly.
In general, I want to design MyMat like as OpenCV cv::Mat
Could you suggest me a proper design ?
1) Using std::vector<uint8_t> data
I have to write some code to remove copy constructor and assignment operator because someone can call them and causes memory copy.
The compiler must support copy ellision and return value optimization.
Always using move assignment and passing by reference are inconvenient
a2 = std::move(a1)
void test(MyMat &mat)
std::queue<MyMat> lists;
lists.push_back(std::move(a1))
..............................
2) Use share_ptr<uint8_t> data
Following this guideline http://www.codingstandard.com/rule/17-3-4-do-not-create-smart-pointers-of-array-type/,
we shouldn't create smart pointers of array type.
3) Use share_ptr< std::vector<uint8_t> > data
To access data, use *(a1.data)[0], the syntax is very inconvenient
4) Use raw pointer, uint8_t *data
Write proper constructor and destructor for this class.
To make automatic memory management, use smart pointer.
share_ptr<MyMat> mat
std::queue< share_ptr<MyMat> > lists;

Matrix classes are normally expected to be a value type with deep copying. So, stick with std::vector<uint8_t> and let the user decide whether copy is expensive or not in their specific context.
Instead of raw pointers for arrays prefer std::unique_ptr<T[]> (note the square brackets).

std::array - fixed length in-place buffer (beautified array)
std::vector - variable length buffer
std::shared_ptr - shared ownership data
std::weak_ptr - expiring view on shared data
std::unique_ptr - unique ownership
std::string_view, std::span, std::ref, &, * - reference to data with no assumption of ownership
Simplest design is to have a single owner and RAII-forced life time ensuring everything that needs to be alive at certain time is alive and needs no other ownership, so generally I'd see if I could live std::unique_ptr<T> before complicating further (unless I can fit all my data on the stack, then I don't even need a unique_ptr).
On a side note - shared pointers are not free, they need dynamic memory allocation for the shared state (two allocations if done incorrectly :) ), whereas unique pointers are true "zero" overhead RAII.

Matrixes should use value semantics, and they should be nearly free to move.
Matrixes should support a view type as well.
There are two approaches for a basic Matrix that make sense.
First, a Matrix type that wraps a vector<T> with a stride field. This has an overhead of 3 instead of 2 pointers (or 1 pointer and a size) compared to a hand-rolled one. I don't consider that significant; the ease of debugging a vector<T> etc makes it more than worth that overhead.
In this case you'd want to write a separate MatrixView.
I'd use CRTP to create a common base class for both to implement operator[] and stride fields.
A distinct basic Matrix approach is to make your Matrix immutable. In this case, the Matrix wraps a std::shared_ptr<T const> and a std::shared_ptr<std::mutex> and (local, or stored with the mutex) width, height and stride field.
Copying such a Matrix just duplciates handles.
Modifying such a Matrix causes you to acquire the std::mutex, then check that shared_ptr<T const> has a use_count()==1. If it does, you cast-away const and modify the data referred to in the shared_ptr. If it does not, you duplicate the buffer, create a new mutex, and operate on the new state.
Here is a copy on write matrix buffer:
template<class T>
struct cow_buffer {
std::size_t rows() const { return m_rows; }
std::size_t cols() const { return m_cols; }
cow_buffer( T const* in, std::size_t rows, std::size_t cols, std::size_t stride ) {
copy_in( in, rows, cols, stride );
}
void copy_in( T const* in, std::size_t rows, std::size_t cols, std::size_t stride ) {
// note it isn't *really* const, this matters:
auto new_data = std::make_shared<T[]>( rows*cols );
for (std::size_t i = 0; i < rows; ++i )
std::copy( in+i*stride, in+i*m_stride+m_cols, new_data.get()+i*m_cols );
m_data = new_data;
m_rows = rows;
m_cols = cols;
m_stride = cols;
m_lock = std::make_shared<std::mutex>();
}
template<class F>
decltype(auto) read( F&& f ) const {
return std::forward<F>(f)( m_data.get() );
}
template<class F>
decltype(auto) modify( F&& f ) {
auto lock = std::unique_lock<std::mutex>(*m_lock);
if (m_data.use_count()==1) {
return std::forward<F>(f)( const_cast<T*>(m_data.get()) );
}
auto old_data = m_data;
copy_in( old_data.get(), m_rows, m_cols, m_stride );
return std::forward<F>(f)( const_cast<T*>(m_data.get()) );
}
explicit operator bool() const { return m_data && m_lock; }
private:
std::shared_ptr<T> m_data;
std::shared_ptr<std::mutex> m_lock;
std::size_t m_rows = 0, m_cols = 0, m_stride = 0;
};
something like that.
The mutex is required to ensure synchonization between multiple threads who are sole owners modifying m_data and the data from the previous write not being synchronzied with the current one.

Related

Another void* topic; I just have to ask because I am confused

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.

Why doesn't boost::lockfree::spsc_queue have emplace?

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.

Most efficient way to assign values to a map of maps

Given a map of maps like:
std::map<unsigned int, std::map<std::string, MyBase*>> m_allMyObjects;
What would be the most efficient way to insert/add/"emplace" an element into m_allMyObjects given an unsigned int and a std::string taking optimization into account (on modern compilers)?
What would be the most efficient way to retrieve an element then?
m_allMyObjects may potentially contain up to 100'000 elements in the future.
Common knowledge and folklore about how to efficiently insert into maps (typically telling you to avoid operator[] and prefering the shiny new emplace) considers the costs of constructing and copying the values in the map. In your case, those values are plain pointers which can be copied at virtually no expense, and copying pointers can be aggressively optimized by the compiler.
On the other hand, you actually do have an object that is expensive to handle, namely the key of type std::string. You need to watch out for copies (moved or copied) of the key to determine performance. Obviously, for the tree lookup, you already need the string object, even if you have it as char*, as there is no insertion function that is templated over the type of key. This means for looking up the place to insert, you use one certain std::string object, but once the map node gets created, the new std::string object inside the map is copy-initialized from it (possibly moved). Avoiding everything in excess of that single copy/move should be your goal.
Example time!
#include <map>
#include <cstdio>
struct noisy {
noisy(int v) : val(v) {}
noisy(const noisy& src) : val(src.val) { std::puts("copy ctor"); }
noisy(noisy&& src) : val(src.val) { std::puts("move ctor"); }
noisy& operator=(const noisy& src)
{ val = src.val; std::puts("copy assign"); return *this; }
noisy& operator=(noisy&& src)
{ val = src.val; std::puts("move assign"); return *this; }
int val;
};
bool operator<(const noisy& a, const noisy& b)
{
return a.val < b.val;
}
int main(void)
{
std::map<noisy,int> m;
std::puts("Operator[]");
m[noisy(1)] = 3;
std::puts("insert/make_pair");
m.insert(std::make_pair(noisy(2), 3));
std::puts("insert/make_pair/ref");
m.insert(std::make_pair<noisy&&,int>(noisy(3), 3));
std::puts("insert/pair/ref");
m.insert(std::pair<noisy&&,int>(noisy(4), 3));
std::puts("emplace");
m.emplace(noisy(5), 3);
}
compiled with g++ 4.9.1, -std=c++11, -O2, the result is
Operator[]
move ctor
insert/make_pair
move ctor
move ctor
insert/make_pair/ref
move ctor
move ctor
insert/pair/ref
move ctor
emplace
move ctor
Which shows: avoid everything that creates an intermediate pair containing a copy of the key! Be aware that std::make_pair does never create a pair that contains references, even if it can take the parameters by reference! Whenever you pass a pair containing the copy of the key, the key gets copied into the pair and later into the map.
The expression suggested by MarkMB, namely m[int_k][str_k] = ptr, is quite good, and likely produces optimal code. There is no reason for the first index (int_k) to not use [], as you want a default constructed sub-map if the index is not used yet, so there is no unnecessary overhead. As we have seen, indexing with the string gets away with a single copy, so you are fine. If you can afford to lose your string, m[int_k][std::move(str_k)] = ptr might be a win, though. As discussed in the beginning, using emplace instead of [] is only about the values, which are virtually free to handle in your case.

push to list of boost::variant's

I have the boost::variant over set of non-default constructible (and maybe even non-moveable/non-copyable and non-copy/move constructible) classes with essentialy different non-default constructor prototypes, as shown below:
#include <boost/variant.hpp>
#include <string>
#include <list>
struct A { A(int) { ; } };
struct B { B(std::string) { ; } };
struct C { C(int, std::string) { ; } };
using V = boost::variant< A const, B const, C const >;
using L = std::list< V >;
int main()
{
L l;
l.push_back(A(1)); // an extra copy/move operation
l.push_back(B("2")); // an extra copy/move operation
l.push_back(C(3, "3")); // an extra copy/move operation
l.emplace_back(4);
l.emplace_back(std::string("5"));
// l.emplace_back(3, std::string("3")); // error here
return 0;
}
I expect, that std::list::emplace_back allows me to construct-and-insert (in single operation) new objects (of all the A, B, C types) into list, even if they have T & operator = (T const &) = delete;/T & operator = (T &&) = delete; and T(T const &) = delete;/T(T &&) = delete;. But what should I do, if constructor is a non-conversion one? I.e. have more, than one parameter. Or what I should to do if two different variant's underlying types have ambiguous constructor prototypes? In my opinion, this is the defect of implementation of the boost::variant library in the light of the new features of C++11 standard, if any at all can be applyed to solve the problem.
I specifically asked about std::list and boost::variant in superposition, because they are both internally implement the pimpl idiom in some form, as far as I know (say, boost::variant currently designed by means of temporary heap backup approach).
emplace can only call the constructors of the type in question. And boost::variant's constructors only take single objects which are unambiguously convertible to one of the variant's types.
variant doesn't forward parameters arbitrarily to one of its bounded types. It just takes a value. A single value that it will try to convert to one of the bounded types.
So you're going to have to construct an object and then copy that into the variant.
Assuming you can modify your "C" class, you could give it an additional constructor that takes a single tuple argument.

C++11 use-case for piecewise_construct of pair and tuple?

In N3059 I found the description of piecewise construction of pairs (and tuples) (and it is in the new Standard).
But I can not see when I should use it. I found discussions about emplace and non-copyable entities, but when I tried it out, I could not create a case where I need piecewiese_construct or could see a performance benefit.
Example. I thought I need a class which is non-copyable, but movebale (required for forwarding):
struct NoCopy {
NoCopy(int, int) {};
NoCopy(const NoCopy&) = delete; // no copy
NoCopy& operator=(const NoCopy&) = delete; // no assign
NoCopy(NoCopy&&) {}; // please move
NoCopy& operator=(NoCopy&&) {}; // please move-assign
};
I then sort-of expected that standard pair-construction would fail:
pair<NoCopy,NoCopy> x{ NoCopy{1,2}, NoCopy{2,3} }; // fine!
but it did not. Actually, this is what I'd expected anyway, because "moving stuff around" rather then copying it everywhere in the stdlib, is it should be.
Thus, I see no reason why I should have done this, or so:
pair<NoCopy,NoCopy> y(
piecewise_construct,
forward_as_tuple(1,2),
forward_as_tuple(2,3)
); // also fine
So, what's a the usecase?
How and when do I use piecewise_construct?
Not all types can be moved more efficiently than copied, and for some types it may make sense to even explicitly disable both copying and moving. Consider std::array<int, BIGNUM> as an an example of the former kind of a type.
The point with the emplace functions and piecewise_construct is that such a class can be constructed in place, without needing to create temporary instances to be moved or copied.
struct big {
int data[100];
big(int first, int second) : data{first, second} {
// the rest of the array is presumably filled somehow as well
}
};
std::pair<big, big> pair(piecewise_construct, {1,2}, {3,4});
Compare the above to pair(big(1,2), big(3,4)) where two temporary big objects would have to be created and then copied - and moving does not help here at all! Similarly:
std::vector<big> vec;
vec.emplace_back(1,2);
The main use case for piecewise constructing a pair is emplacing elements into a map or an unordered_map:
std::map<int, big> map;
map.emplace(std::piecewise_construct, /*key*/1, /*value*/{2,3});
One power piecewise_construct has is to avoid bad conversions when doing overload resolution to construct objects.
Consider a Foo that has a weird set of constructor overloads:
struct Foo {
Foo(std::tuple<float, float>) { /* ... */ }
Foo(int, double) { /* ... */ }
};
int main() {
std::map<std::string, Foo> m1;
std::pair<int, double> p1{1, 3.14};
m1.emplace("Will call Foo(std::tuple<float, float>)",
p1);
m1.emplace("Will still call Foo(std::tuple<float, float>)",
std::forward_as_tuple(2, 3.14));
m1.emplace(std::piecewise_construct,
std::forward_as_tuple("Will call Foo(int, double)"),
std::forward_as_tuple(3, 3.14));
// Some care is required, though...
m1.emplace(std::piecewise_construct,
std::forward_as_tuple("Will call Foo(std::tuple<float, float>)!"),
std::forward_as_tuple(p1));
}

Resources