Opened 10 years ago

Closed 10 years ago

Last modified 10 years ago

#7167 closed Bugs (invalid)

interprocess_condition doesn't implement move semantics

Reported by: John DiMatteo <jdimatteo@…> Owned by: Ion Gaztañaga
Milestone: To Be Determined Component: interprocess
Version: Boost 1.51.0 Severity: Problem
Keywords: Cc: jdimatteo@…

Description

Boost.Interprocess containers support move semantics, but interprocess_condition does not, which is problematic.

For example, the lack of move semantics prevents having a boost::interprocess::map where the values are structs containing interprocess_condition variables. This is because map insert requires the value object to have move or copy constructors, both of which are impossible to implement correctly since the struct contains the non-copyable and non-moveable interprocess_condition member. (A work around is to store a pointer to the interprocess_condition in the Struct, but that shouldn't be necessary).

Change History (4)

comment:1 by John DiMatteo <jdimatteo@…>, 10 years ago

This was discussed in the #boost irc.freenode.net channel a little bit:

12:32 < JohnD> I have a boost::interprocess::map<pid_t, MyStruct, std::less<pid_t>, MyAllocator> which was working fine until I added a boost::interprocess::interprocess_condition variable to MyStruct, and now I can't compile because it needs a copy constructor -- why would I need a copy constructor if I'm not using the map [] syntax?
12:42 < Zao> A wild guess would be that that container, like most containers, copy on insertion.
12:44 < mjcaisse> I agree with Zao, though I'm having trouble finding that wording in the docs. interprocess containers are move aware though ... so you should be able to work around it.
12:44 < mjcaisse> JohnD:
2:45 < JohnD> mjcaisse / Zao: thanks, that I just found when I remove my insert I no longer need the copy constructor
12:45 < JohnD> so now I just need to see if I can get the move semantics working -- I was inserting a temporary so I thought move was implicit
12:46 < mjcaisse> JohnD: http://www.boost.org/doc/libs/1_50_0/doc/html/interprocess/allocators_containers.html#interprocess.allocators_containers.containers_explained.containers_and_move
12:47 < mjcaisse> JohnD: hmmm... that doesn't look helpful (o; I wonder if you can implement a "proper" constructor that will enable move for the container.
12:49 < JohnD> mjcaisse: that sounds promising, MyStruct doesn't have any constructor specifically for move, I'll try that -- thanks!
13:10 < JohnD> mjcaisse: thanks, defining the move constructor fixed the problem, but I can't seem to get std::move nor boost::move to work with boost::interprocess::interprocess_condition
13:10 < JohnD> is boost::interprocess::interprocess_condition move aware?
13:11 < mjcaisse> JohnD: it *should* work with boost::move
13:11 < JohnD> (to be clear, the move constructor I defined compiles but is incorrect since I'm not properly moving the condition member variable)
13:12 < JohnD> mjcaisse: I'm using boost 1.49, and looking at interprocess_condition.hpp doesn't seem to show any move constructor being defined
13:17 < mjcaisse> JohnD: hmmm... I'm seeing the same thing )o:
13:22 < JohnD> the lack of a move constructor in interprocess_condition.hpp is a bug, right? is there a work around?
13:22 < JohnD> I think it is probably more likely that I'm doing something wrong, I'm skeptical I could actually find a bug in boost
13:24 < mjcaisse> JohnD: (o;
13:26 < mjcaisse> JohnD: so you are calling something like: my_map.insert( boost::move( pair<key,value>(k,v) ) )
13:26 < mjcaisse> JohnD: which doesn't seem right either ....
13:28 < JohnD> mjcaisse: I'm doing the following: my_map.insert(std::pair<const pid_t, MyStruct>(aPID, MyStruct(mManagedSharedMemory, blah, blah)))
13:29 < JohnD> and that compiles fine as long as I defined the MyStruct(MyStruct&& a)
13:30 < JohnD> the problem lies when I try to move the interprocess_condition in that move constructor -- it isn't allowed
13:38 < JohnD> mjcaisse: I guess I don't *really* need to move the interprocess_condition member in the move constructor of MyStruct -- if I am only doing the move constructor when inserting into the map there is nothing worth moving anyway -- does this sound right to you? obviously this is dangerous (e.g. in case someone else tries to use my move constructor outside of inserting a temporary), but I don't see what other options I have -- what do you think?
13:42 < mjcaisse> JohnD: that would be a way around the problem
13:42 < mjcaisse> JohnD: you could also do something sleazy like: MyStruct& v = my_map[key]; and then "initialize" v
13:45 < mjcaisse> JohnD: I see all of the example code is putting conditional variables and such into shared memory via new. I can't find anything via google on people trying to put them in containers
13:45 < mjcaisse> JohnD: but that seems like a perfectly normal use-case
13:53 < JohnD> mjcaisse: actually one of my coworkers just suggested I store the interprocess_condition as a pointer which would make the move semantics unnecessary (which I guess agrees with your googling), so I'll just do that for now
13:55 < mjcaisse> JohnD: the trick is you want to store it in shared memory (o;

comment:2 by viboes, 10 years ago

Component: Noneinterprocess
Owner: set to Ion Gaztañaga

comment:3 by Ion Gaztañaga, 10 years ago

Resolution: invalid
Status: newclosed

It's not possible to add move semantics to condition variables and mutexes, because the operating system but might store the address of the synchronization object internally. Because of this, pthread_xxx_t is not copyable and std::mutex and std::condition_variable are not copyable or movable.

The only way to put objects with member conditions and mutexes in containers is to use node-based containers (list, map, set, stable_vector...) and use emplace(...) functions, which don't require move constructible elements.

comment:4 by John DiMatteo <jdimatteo@…>, 10 years ago

igaztanaga: sorry for the invalid bug report and thanks for the explanation!

Note: See TracTickets for help on using tickets.