[openbeos] Re: A new BMessage implementation (Message4)

  • From: Ingo Weinhold <bonefish@xxxxxxxxxxxxxxx>
  • To: openbeos@xxxxxxxxxxxxx
  • Date: Fri, 11 Nov 2005 23:59:29 +0100

On 2005-11-11 at 13:54:56 [+0100], mmlr@xxxxxxxx wrote:
[...]
> > This could be dangerous if both applications
> > (sender and receiver) have full write access
> > to the message.
> 
> Obviously, but that was not how I planned it. I thought that the one
> "receiving" the message takes the area as read only and then, when it
> needs to write to it, makes a copy for it's own purposes. That's how I
> understood copy-on-write at least.

That's how I understand it, too, but I was thinking of a practical problem: 
If an application is buggy and trashes memory, it can as well trash a 
shared message area, even if it is algorithmically not allowed to write to 
it. One could make the area actually read-only (set_area_protection()), but 
that might not only be expensive but even impractical (the reference 
counter will have to live in that area).

> The other thing that comes to mind is obviously: What if the "sender"
> writes to the message after it is referenced by someone else? In that
> case, the sender would have to make a copy too. I thought of something
> like this:
> 
> 1. We have a large message that is located in an area.
> 2. The data has a reference count of 1 (ourselfs).
> 3. The message is sent with the area_id as a pointer to the the shared
> area.
> 4. The receiver increments the reference count.
> 5. Both sender and receiver have read only access to the buffer.
> 6. One of both needs to write something, makes a copy of the area and
> decrements the reference count of the original data.
> 7. The other one needs to write something, it sees that the reference
> count is 1 and can use the area directly (no copy).
> 
> Does that concept work or do I miss something? The area, or the buffer
> inside the same application for that matter, would only be copied when
> more than one party currently uses the data (reference count > 1). The
> last message that gets deleted (the one decrementing the reference
> count to 0) would be the last "owner" of the data and delete it. This
> concept should work for both, intra application with shared buffers and
> inter application with shared areas.

For intra-app messaging that sounds fine. For inter-app messaging I wrote 
my objections above. How I think, it could work in this case is:

3. The sender clones the area copy-on-write into the receiver's team (IIRC 
Axel already implemented a system call for cloning into another team; don't 
know if copy-on-write is possible) and sends the ID of the cloned area to 
the receiver.
4. The receiver checks the message data for validity and initializes the 
reference count to 1.

An open question is whether it is possible to resize a copy-on-write area 
(only on one end). Axel?

> By the way, this whole thing would go into the assignment operator,
> wouldn't it?

If you put incrementing and decrementing the reference counter and dealing 
with the respective consequences into separate methods, the assignment 
operator shouldn't do much more than invoking those. The prepare-for-write 
part that copies the data if necessary should go into a another method 
invoked by Add*(), Remove*(), Replace*() and friends. At least that's how I 
would implement it.

CU, Ingo

Other related posts: