2

I have a std::vector<std::atomic_bool> that I want to resize to some arbitrary n, wherein all newly created objects are assigned a value of true. The program will not build because resize() relies on the copy constructor of the data type, not its assignment operator. Is there any way to assign a default value to an atomic_bool or would I be stuck with using a loop and store()ing all the values?

What I've tried:

#include <atomic>
#include <vector>

class foo() {
public:
    std::vector<std::atomic_bool> vec;

    foo() {
        std::atomic_bool temp(true);

        vec.resize(100, std::atomic_bool(true)); //try 1

        vec.resize(100, temp); //try 2
    }
}
Stephen
  • 1,498
  • 17
  • 26
  • 4
    It doesn't make sense to stick atomic types into a vector. Atomic types are designed to be accessed by multiple threads, and that doesn't seem to be useful when the elements can be relocated. If you don't want reallocation, just make the vector with size 100 right from the start ([Demo](http://melpon.org/wandbox/permlink/UHlG7obdmMgslfxx)). – Kerrek SB Jun 16 '16 at 23:06
  • @KerrekSB I think it is fine. You can read vector from multiple threads as long as no thread is trying to modify the vector. – Bryan Chen Jun 16 '16 at 23:08
  • @BryanChen; Sure, you can, but it doesn't make sense. There's no usecase for that. – Kerrek SB Jun 16 '16 at 23:10
  • 2
    @KerrekSB I don't want to resize the vector concurrently, and the size of the vector will be determined at run time so I figured a vector was a good choice for the simple fact that it can assign values while it resizes. – Stephen Jun 16 '16 at 23:10
  • @KerrekSB A use case is change application settings. I can pause/kill all worker threads, modify the vector, resume/restart workers. – Bryan Chen Jun 16 '16 at 23:12
  • @KerrekSB Your demo works but it doesnt work if I have to resize the vector at run time. – Stephen Jun 16 '16 at 23:21
  • 1
    @Stephen: Correct. Don't resize the vector at runtime. Encapsulate that logic at a higher level and create a new object of that higher-level concept whenever the size changes. – Kerrek SB Jun 16 '16 at 23:22
  • A more stringent problem of adding atomic types into a vector is that atomics are not copiable nor movable, so you can't call `resize` on such a vector. – peppe Jun 16 '16 at 23:26

3 Answers3

8

If T is neither copyable nor movable, then std::vector<T> cannot be resized. Period. In this case, you might want to consider std::deque.

std::deque<std::atomic_bool> D;
D.emplace_back(true);  // write a helper to do this 100 times if you want

However, note that a standard library container of atomics is not atomic; adding new elements to the container is not an atomic operation so you will probably have to protect the container with a mutex, which might eliminate any benefits of storing atomics inside.

Brian Bi
  • 111,498
  • 10
  • 176
  • 312
1

Brian's suggestion of a deque is sound and still allows O(1) random access, though I'd expect it to be a couple times slower than a vector. Kerrek's suggestion of a higher level class managing a vector's also workable.

FWIW, another option is wrapping the individual std::atomic_bools with a type that orchestrates copy construction as a combination of default construction and assignment:

struct Copy_Constructible_Atomic_Bool : std::atomic_bool
{
    Copy_Constructible_Atomic_Bool(const std::atomic_bool& rhs)
    {
        std::atomic_bool::operator=(rhs);
    }

    Copy_Constructible_Atomic_Bool(const Copy_Constructible_Atomic_Bool& rhs)
    {
        std::atomic_bool::operator=(rhs);
    }
};

Usage:

std::vector<Copy_Constructible_Atomic_Bool> vec;
std::atomic_bool temp;
temp = true;
vec.resize(100, temp);
Tony Delroy
  • 102,968
  • 15
  • 177
  • 252
-2

atomics aren't designed to be moved, so you cant reallocate them to be somewhere else. However, you can replace them.

vec = std::vector<std::atomic_bool>(100, true);

(I'm not 100% certain you can use true here, but I believe you can.)

Mooing Duck
  • 64,318
  • 19
  • 100
  • 158