Recently I have read a part of "Concurrency in action" book concerning parallel quicksort implementation. I tried to check the code mentioned in the book and received an error on this part:
struct listPart
{
list<T> data;
promise<list<T>> promise;
};
listPart newLowerPart;
...
parts.push(move(newLowerPart));
The compiler gives the error
std::promise::promise(const std::promise> &) : attempting
to reference a deleted function.
The error is occured in generated copy constructor of listPart.
I guess trying to move newLowerPart it tries to use deleted copy constructor of promise. I thought creating custom copy constructor would help, but even an attempt to move promise inside it gave me the same error. Could you help me to solve this problem?
Thank you in advance
The problem is likely with your parts container implementation - it tries to copy the push parameter instead of moving it.
Here is an example:
#include <list>
#include <future>
struct listPart
{
std::list<int> data;
std::promise<std::list<int>> p;
};
template<typename T>
class dummy_container{
T t_;
public:
void push_back(const T& t){
t_ = t;
}
void move_back(const T& t){
t_ = t;
}
void move_back(T&& t){
t_ = std::move(t);
}
};
int main() {
dummy_container<listPart> dc;
listPart lp;
//dc.push_back(std::move(lp)); // won't compile, function only handles const references
dc.move_back(std::move(lp)); // will compile, because it moves if possible
}
Remember, that correct handling rvalues requires special treatment. So your container should provide at least two versions of push:
void push(const T& t); //'t' is coopied
and
void push(T&& t); //'t' is moved
Also, you should define move constructor for listPart and forbid copying:
Solution:
struct listPart
{
list<T> data;
promise<list<T>> promise;
listPart(const listPart&) = delete;
listPart(listPart&& source)
: data(std::move(source.data))
, promise(std::move(source.promise))
{ }
};
I thought creating custom copy constructor would help
As I demonstrated, you shouldn't define copy constructor for listPart - it should either be deleted or (in case of pre-C++ 11) private with no implementation provided. That's because copying std::promise is not defined (its copy constructor is deleted), so copying instance of listPart is meaningless in this case.
Related
I need to create a simple template container, which can store any object of any type and could be used everywhere. So, I did something like this:
template <typename Type>
class Container {
public:
Container() : arraySize(10) { valueWrappers = new Type[arraySize];}
Container(const Container& other) { /* --- */}
~Container() { /* --- */}
Container& operator=(const Container& other) { /* --- */}
/* some functions */
private:
int arraySize;
Type* valueWrappers;
};
Now I have the problem - when I'm trying to create my container using as template a class without default constructor, the compilation error appears:
class MyClass {
public:
MyClass(int value) :v(value) { }
private:
int v;
};
int main() {
Container<MyClass> cont;
return 0;
}
C2512 'MyClass': no appropriate default constructor available
The problem is that I need to initialize the array of "Type" values with something, but I don't no what I need to use. I can't use NULL because, in this case, Container will work only with pointers. So, can somebody give an advice, how am I able to do it? Or, maybe, there is another way to solve this task?
Based on your requirements, I think you're going to have to use placement new. Since you haven't provided all the relevant code, I'm going to do what I can.
First, you're going to have to allocate raw memory instead of using new directly.
Container() : arraySize(10) { valueWrappers = reinterpret_cast<Type*>(::operator new(sizeof(Type) * arraySize)); }
Now when you put something in your Container, you'll have to construct it in place, using something like the following:
new (valueWrappers + index) Type(arguments to type);
In your destructor, you'll need to explicitly call the destructors on any object that you used placement new for.
valueWrappers[index]->~Type();
Lastly, release the memory using ::operator delete.
::operator delete(valueWrappers);
Please bear in mind that this is a very quick and dirty answer, and this code can be hard to debug and maintain. You're going to have to keep track of what indexes in valueWrapper have been initialized and which haven't during cleanup. If possible, I highly recommend using something akin to std::vector, which handles all this complexity for you.
One option is to not allocate the array in the default constructor, but initialise valueWrappers to null instead. Another option is to not have a default constructor in your template. Third option is to keep your class as-is and simply document that the template is default constructible only if the type argument is default constructible.
You can use std::optional to defer initialization, which is guaranteed to handle object lifetime correctly. Letting a default constructed container have 10 elements is also a questionable choice — a (count) constructor may be preferable.
template <typename Type>
class Container {
using elem_t = std::optional<Type>;
std::size_t count{};
std::unique_ptr<elem_t[]> elems{};
public:
Container() = default;
Container(std::size_t cnt)
: count{cnt}
, elems{std::make_unique<elem_t[]>(cnt)}
{
}
// for example
template <typename... Args>
void construct_at(std::size_t pos, Args&&... args)
{
assert(pos < count);
assert(!elems[pos]);
elems[pos].emplace(std::forward<Args>(args)...);
}
// ...
};
Note that I used std::unique_ptr to simplify memory management; a pointer will also be OK, though apparently more error-prone. Now you can traverse the container and construct the elements:
class MyClass {
public:
MyClass(int value) :v(value) { }
private:
int v;
};
int main()
{
Container<MyClass> cont(10);
for (std::size_t i = 0; i < 10; ++i) {
cont.construct_at(i, /* argument */);
}
}
I'm trying to create a very simple, bare-bones C++ class to implement a thread-safe list, i.e. one which is automatically locked when you access it. Unfortunately, the compiler doesn't want to allow me to create and return a struct that contains a unique_lock. This is what I tried at first:
template<typename T>
struct LockedQueue {
private:
std::mutex mutex;
using lock_t = std::unique_lock<std::mutex>;
std::list<T> underlying_list;
public:
struct LockedListAccess {
private:
lock_t lock;
public:
std::list<T> &access;
};
LockedListAccess locked() {
return LockedListAccess{ lock_t{mutex}, underlying_list };
}
};
This fails with
no matching function for call to ‘LockedQueue<tcp::socket>::LockedListAccess::LockedListAccess(<brace-enclosed initializer list>)
I'm guessing this means that brace initializer lists/C++11 unified initialization for structs don't work with move-only types like std::unique_lock. So I tried creating an explicit constructor for my struct that takes the unique_lock as an rvalue reference, and moves it into the member:
template<typename T>
struct LockedQueue {
private:
std::mutex mutex;
using lock_t = std::unique_lock<std::mutex>;
std::list<T> underlying_list;
public:
struct LockedListAccess {
private:
lock_t lock;
public:
std::list<T> &access;
LockedListAccess(lock_t&& l, std::list<T>& a) :
lock(l), access(a) {};
};
LockedListAccess locked() {
return LockedListAccess{ std::move(lock_t{mutex}), underlying_list };
}
};
However, this also fails, giving me the error
error: use of deleted function ‘std::unique_lock<_Mutex>::unique_lock(const std::unique_lock<_Mutex>&) [with _Mutex = std::mutex]’
This compiler error is especially confusing, because it points at the line containing lock(l), access(a) as the one where I'm trying to use the deleted copy constructor of std::unique_lock. I declared l as a lock_t&&, so how could I possibly be calling the copy constructor?
Most resources I could find on the internet seem to indicate that you can move unique_locks around with std::move, though no one seems to address the question of how to construct an object that contains a unique_lock by using std::move. What could I be doing wrong here?
Problem:
In the context of the LockedListAccess constructor, lock_t&& l is actually an l-value. So you need to cast it back to an r-value using std::move. General rule of thumb: Always std::move r-value references and always std::forward forwarding references.
Solution:
LockedListAccess(lock_t&& l, std::list<T>& a)
: lock(std::move(l))
, access(a)
{}
Also you do not need to move the temporary lock object because the compiler will automatically bind a temp object to an r-value reference.
This:
LockedListAccess locked() {
return LockedListAccess{ std::move(lock_t{mutex}), underlying_list }
}
can become this:
LockedListAccess locked() {
return LockedListAccess{ lock_t{mutex}, underlying_list }
}
I have a class template S<T> and because the template parameter is sometimes hard write explicitly I also have a little helper function makeS(...) to deduce the template parameter.
Now the problem is that the constructor of S has a "side effect": it adds itself to a map which then will later be used to iterate over all instances of S. But this effectively makes S<T> s{...}; very different from auto s = makeS(...); (if RVO is not used).
Here is some code which hopefully shows what I'm trying to do. (Note: in the actual program, S has more than a single template parameter and all will be deduced in makeS)
#include <cassert>
#include <iostream>
#include <map>
#include <string>
#include <utility>
using namespace std;
struct Base
{
virtual ~Base() {}
virtual void f() const = 0;
};
static map<string, Base*> Map;
template <typename T>
struct S : Base
{
T Func;
Base* This;
S(string const& name, T func) : Func(std::move(func)), This(this)
{
//
// Automatically add this struct to Map...
//
Map.insert({name, this});
}
virtual void f() const override { Func(); }
};
template <typename T>
S<T> makeS(std::string const& name, T func)
{
return S<T>(name, std::move(func));
}
void func1()
{
std::cout << "func1\n";
}
int main()
{
struct Func2
{
void operator ()() const {
std::cout << "func2\n";
}
};
//
// This is not possible:
//
// S< ??? > s("s", [](){});
//
// This would be ok:
//
// auto F = [](){};
// S<decltype(F)> s("s", F);
//
auto s1 = makeS("s1", func1);
auto s2 = makeS("s2", Func2());
auto s3 = makeS("s3", [](){ std::cout << "func3\n"; });
//
// Manually adding s1,... to the Map is ok, but that's what
// I want to avoid...
//
// Map.insert({"s1", &s1});
// ...
//
assert(&s1 == s1.This);
assert(&s2 == s2.This);
assert(&s3 == s3.This);
for (auto&& I : Map)
{
I.second->f();
}
}
As I understand it, the map will only contain valid pointers if RVO is used in auto s1 = makeS(...) etc. and this is not guaranteed.
Is there a way to deduce the template parameters while at the same time avoiding the need to manually register s1,...?
Your basic problem is you failed to implement the rule of 3. If your destructor needs non-trivial behavior (and if you register yourself in the constructor, this is the case), you must either implement or block assignment and copy construct (and/or move-assign and move-construct).
In this case, we can implement a move-construct and block move-assign, and copy construct and copy assign are implicitly blocked.
First, add name to S. Then implement a move constructor.
template <typename T>
struct S : Base
{
std::string Name;
T Func;
Base* This; // ?? why ?? this looks both dangerous and useless at the same time!
S( S&& s ): Name(std::move(s.Name)), Func(std::move(s.Func)), This(this) {
s.clear(); // technically `move` need not clear.
map[Name] = this; // overwrite
}
S& operator=(S&& s) = delete; // or implement it
now your object is moveable, and when moved it updates the Map. ~S should, I assume, unregister from Map -- detect if your name is empty (and assert at construction you gain a non-empty name), and if it is don't unregister (as you where already moved from).
Now move-construct and elided-construct have the same semantics. RVO failure results in some inefficiency, but no logical failure. Plus, your type is now moveable, which tends to be really useful.
If you need to maintain object identity, use can use std::unique_ptr:
template <typename T>
std::unique_ptr<S<T>> makeS(std::string const& name, T func)
{
return { new S<T>(name, std::move(func)) };
}
Now moving the pointer from place to place won't move the object; the pointer kept in the map will stay valid.
My suggestions to improve your code:
1) Get rid of the side effect in the constructor. Create objects in a factory method only (makeS in your code; you can make it a static member function of S) and register the S objects in that method. To disable object creation in different ways make constructor(s) private.
2) Disable S objects copying/moving and handle the objects for example as shared_ptr/unique_ptr<S> only. When you disable copying/moving you avoid the problem when your map contains a pointer to invalid objects and now you don't need to rely on RVO.
3) Use std::function<void()> instead of T Func;. In that case your class don't need to be a template class (or it will have less template arguments). That will simplify your code.
I was implementing (for training purpose) a Bubble Sort template function:
template<typename iterInput,
typename predicate>
void BubbleSort(iterInput first1,iterInput last1,predicate func)
{
bool swapped(false);
do
{
swapped = false;
iterInput begin = first1;
iterInput beginMinus = first1;
++begin;
for (;begin != last1; begin++,beginMinus++)
{
if (func(*beginMinus,*begin) )
{
std::swap(*beginMinus,*begin);
swapped = true;
}
}
}
while(swapped);
}
When I have realized that this function will not work for class with no assignment operator, like this one (forgive me for the bad name):
class NoCopyable
{
public:
explicit NoCopyable(int value) : value_(value) {}
NoCopyable(const NoCopyable& other) : value_(other.value_) {}
~NoCopyable() {}
bool operator<(const NoCopyable& other) { return value_ < other.value_; }
void setValue(int value) { value_ = value; }
std::ostream& print(std::ostream& os) const { return os << value_; }
private:
NoCopyable& operator=(const NoCopyable& other);
int value_;
};
std::ostream& operator<<(std::ostream& os, const NoCopyable& obj)
{
return obj.print(os);
}
struct PrintNoCopyable
{
void operator()(const NoCopyable& noCopyable) { std::cout << noCopyable << '\n'; }
};
The compiler raises this error Error 1 error C2248: 'NoCopyable::operator =' : cannot access private member declared in class 'NoCopyable'
So, I have slightly modify the code using instead of the std::swap function my version of the swap function, here is the code:
template<typename T1,
typename T2>
void noAssignmentSwap(T1& t1,T2& t2)
{
T1 temp(t1);
t1.~T1();
new (&t1) T1(t2);
t2.~T2();
new (&t2) T2(temp);
}
The code compiles and gives the right result. However I am not completely sure, I remember a Sutter's article that suggest you to avoid playing with the objects life time. The article just warns you by playing with fire without actually giving you any real reason. I can see problem in exception safety if the copy constructor of T1 or T2 can throw. However there is the same problem in the standard version if the assignment operator is allowed to throw.
Here the question, can you see any possible drawbacks in this version of swap?
Cheers
Apart from anything else, if a class does not have an assignment operator, its designer probably did not intend it to be swapped. If they did that, they probably disabled copy construction too, so your new swap function still won't work.
As for your assertion that Standard Library containers do not need assignment - that is true so long as you don't want to actually do anything useful with them. Does this code compile for you?
#include <vector>
using namespace std;
struct A {
private:
void operator=( const A &);
};
int main() {
vector <A> v;
v.push_back( A() );
v[0] = A(); // assignment needed here
}
I think it won't.
The difference is that when the assignment operator fails, you still have the same number of objects.
If you destroy one object and fail to create a new one, one object is lost! If it was part of a container, the container's state is probably also invalid.
You need a copy ctor instead of an assignment operator, but the two are sufficiently similar that at least in a typical case, you'll have both or you'll have neither. IOW, I don't think this generally accomplishes much.
I'd class it right along side the xor-swap trick: interesting, but generally useless.
It might be confusing to a future maintainer of the code.
I need to work with array from several threads, so I use CRITICAL SECTION to give it an exclusive access to the data.
Here is my template:
#include "stdafx.h"
#ifndef SHAREDVECTOR_H
#define SHAREDVECTOR_H
#include <vector>
#include <windows.h>
template<class T>
class SharedVector {
std::vector<T> vect;
CRITICAL_SECTION cs;
SharedVector(const SharedVector<T>& rhs) {}
public:
SharedVector();
explicit SharedVector(const CRITICAL_SECTION& CS);
void PushBack(const T& value);
void PopBack();
unsigned int size() const;
T& operator[](int index);
virtual ~SharedVector();
};
template<class T>
SharedVector<T>::SharedVector() {
InitializeCriticalSection(&cs);
}
template<class T>
SharedVector<T>::SharedVector(const CRITICAL_SECTION& r): cs(r) {
InitializeCriticalSection(&cs);
}
template<class T>
void SharedVector<T>::PushBack(const T& value) {
EnterCriticalSection(&cs);
vect.push_back(value);
LeaveCriticalSection(&cs);
}
template<class T>
void SharedVector<T>::PopBack() {
EnterCriticalSection(&cs);
vect.pop_back();
LeaveCriticalSection(&cs);
}
template<class T>
unsigned int SharedVector<T>::size() const {
EnterCriticalSection(&cs);
unsigned int result = vect.size();
LeaveCriticalSection(&cs);
return result;
}
template<class T>
T& SharedVector<T>::operator[](int index) {
EnterCriticalSection(&cs);
T result = vect[index];
LeaveCriticalSection(&cs);
return result;
}
template<class T>
SharedVector<T>::~SharedVector() {
DeleteCriticalSection(&cs);
}
While compiling I have such a problem for calling EnterCriticalSection(&cs) and LeaveCriticalSection(&cs):
'EnterCriticalSection' : cannot convert parameter 1 from
'const CRITICAL_SECTION *' to 'LPCRITICAL_SECTION'
I do not know what is wrong. May be you can see. Just because I always used it this way and it was alright. windows.h is included
Just declare cs as:
mutable CRITICAL_SECTION cs;
or else remove the const clause on size()
Entering a critical section modifies the CRITICAL_SECTION, and leaving modifies it again. Since entering and leaving a critical section doesn't make the size() method call logically non-const, I'd say leave it declared const, and make cs mutable. This is the type of situation mutable was introduced for.
Also - take a look at Martin York's and Joe Mucchiello's suggestions - use RAII whenever possible to deal with any kind of resources that need to be cleaned up. This works just as well for critical sections as it does for pointers and file handles.
Also the code above is not Exception safe.
There is no guarantee that push_back() pop_back() will not throw. If they do they will leave your critical section permanently locked. You should create a locker class that calls EnterCriticalSection() on construction and LeaveCriticalSection() on destruction.
Also this makes your methods a lot easier to read. (see below)
class CriticalSectionLock
{
public:
CriticalSectionLock(CRITICAL_SECTION& cs)
: criticalSection(cs)
{
EnterCriticalSection(&criticalSection);
}
~CriticalSectionLock()
{
LeaveCriticalSection(&criticalSection);
}
private:
CRITICAL_SECTION& criticalSection;
};
// Usage
template
unsigned int SharedVector::size() const
{
CriticalSectionLock lock(cs);
return vect.size();
}
Another thing you should worry about. Is making sure that when you destroy the object you have ownership and that nobody else tries to take ownership during destruction. Hopefully your DestoryCriticalSection() takes care of this.
I prefer using a separate Acquisition object over your code. Your code if fragile when an exception occurs between the Enter and Leave calls:
class CS_Acquire {
CRITICAL_SECTION &cs;
public:
CS_Acquire(CRITICAL_SECTION& _cs) : cs(_cs) { EnterCriticalSection(cs); }
~CS_Acquire() { LeaveCriticalSection(cs); }
};
Then in your class methods you would code it as:
template <typename T>
void SharedVector::PushBack(const T& value) {
CS_Acquire acquire(&cs);
vect.push_back(value);
}
EnterCriticalSection doesn't take a const argument. That's a compilation error, BTW, not a linking error...
Also, are you sure you want to pass in a critical section into your ctor, and then have the ctor perform the InitializeCriticalSection call? If you want to share your critical section, I suppose you'd initialize it first, and then hand it out.
I see you have declared an empty copy constructor:
SharedVector(const SharedVector& rhs) {}
As I'm sure you are aware, this function does nothing, and it also leaves cs uninitialised. Because your class contains an instance of a CRITICAL_SECTION, you must be sure to disallow copy constructor and assignment operator calls unless you are going to implement them completely. You can do this by placing the following declarations in the private section of your class:
SharedVector(const SharedVector &);
SharedVector &operator=(const SharedVector &);
This prevents the compiler from auto-generating incorrect versions of these methods, and also prevents you from calling them in other code you write (because these are only declarations, but not definitions with {} code blocks).
Also, as Arnout mentioned, the constructor that takes a CRITICAL_SECTION& argument seems wrong. What your implementation does is copy the passed-in critical section to cs (which is not a valid thing to do with a CRITICAL_SECTION), then calls InitializeCriticalSection(&cs) which overwrites the copy you just did and creates a new critical section. To the caller who passed in a critical section, this seems to do the wrong thing by effectively ignoring whatever was passed in.
so, it`s something wrong with access rights.
I made size() method non-const and now it is ok.