Make it possible to properly use operator= on BCursors by making sure the

reference counting is maintained correctly in the app_server. While reviewing
this code, I have my doubts that my previous solution for handling pending
SetViewCursor() calls is always working as it is intended.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@31131 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Stephan Aßmus 2009-06-20 10:10:01 +00:00
parent 76d87570c9
commit 5d62f8e0e5
4 changed files with 116 additions and 31 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright 2006, Haiku, Inc. All Rights Reserved.
* Copyright 2006-2009, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef _CURSOR_H
@ -11,31 +11,39 @@
class BCursor : BArchivable {
public:
BCursor(const void* cursorData);
BCursor(BMessage* data);
virtual ~BCursor();
public:
BCursor(const void* cursorData);
BCursor(const BCursor& other);
BCursor(BMessage* data);
virtual ~BCursor();
virtual status_t Archive(BMessage* archive, bool deep = true) const;
static BArchivable* Instantiate(BMessage* archive);
virtual status_t Archive(BMessage* archive,
bool deep = true) const;
static BArchivable* Instantiate(BMessage* archive);
private:
virtual status_t Perform(perform_code d, void* arg);
BCursor& operator=(const BCursor& other);
bool operator==(const BCursor& other) const;
bool operator!=(const BCursor& other) const;
virtual void _ReservedCursor1();
virtual void _ReservedCursor2();
virtual void _ReservedCursor3();
virtual void _ReservedCursor4();
private:
virtual status_t Perform(perform_code d, void* arg);
private:
friend class BApplication;
friend class BView;
virtual void _ReservedCursor1();
virtual void _ReservedCursor2();
virtual void _ReservedCursor3();
virtual void _ReservedCursor4();
int32 fServerToken;
bool fNeedToFree;
mutable bool fPendingViewCursor;
void _FreeCursorData();
uint32 _reserved[6];
private:
friend class BApplication;
friend class BView;
int32 fServerToken;
bool fNeedToFree;
mutable bool fPendingViewCursor;
uint32 _reserved[6];
};
#endif // _CURSOR_H

View File

@ -68,6 +68,7 @@ enum {
AS_QUERY_CURSOR_HIDDEN,
AS_CREATE_CURSOR,
AS_REFERENCE_CURSOR,
AS_DELETE_CURSOR,
AS_BEGIN_RECT_TRACKING,

View File

@ -63,6 +63,16 @@ BCursor::BCursor(const void *cursorData)
}
BCursor::BCursor(const BCursor& other)
:
fServerToken(-1),
fNeedToFree(false),
fPendingViewCursor(false)
{
*this = other;
}
BCursor::BCursor(BMessage *data)
{
// undefined on BeOS
@ -74,14 +84,7 @@ BCursor::BCursor(BMessage *data)
BCursor::~BCursor()
{
// Notify server to deallocate server-side objects for this cursor
if (fNeedToFree) {
BPrivate::AppServerLink link;
link.StartMessage(AS_DELETE_CURSOR);
link.Attach<int32>(fServerToken);
link.Attach<bool>(fPendingViewCursor);
link.Flush();
}
_FreeCursorData();
}
@ -101,6 +104,42 @@ BCursor::Instantiate(BMessage *data)
}
BCursor&
BCursor::operator=(const BCursor& other)
{
if (&other != this && other != *this) {
_FreeCursorData();
fServerToken = other.fServerToken;
fNeedToFree = other.fNeedToFree;
fPendingViewCursor = false;
if (fNeedToFree) {
// Tell app_server that there is another reference for this
// cursor data!
BPrivate::AppServerLink link;
link.StartMessage(AS_REFERENCE_CURSOR);
link.Attach<int32>(fServerToken);
}
}
return *this;
}
bool
BCursor::operator==(const BCursor& other) const
{
return fServerToken == other.fServerToken;
}
bool
BCursor::operator!=(const BCursor& other) const
{
return fServerToken != other.fServerToken;
}
status_t
BCursor::Perform(perform_code d, void *arg)
{
@ -112,3 +151,18 @@ void BCursor::_ReservedCursor1() {}
void BCursor::_ReservedCursor2() {}
void BCursor::_ReservedCursor3() {}
void BCursor::_ReservedCursor4() {}
void
BCursor::_FreeCursorData()
{
// Notify server to deallocate server-side objects for this cursor
if (fNeedToFree) {
BPrivate::AppServerLink link;
link.StartMessage(AS_DELETE_CURSOR);
link.Attach<int32>(fServerToken);
link.Attach<bool>(fPendingViewCursor);
link.Flush();
}
}

View File

@ -939,7 +939,7 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver& link)
if (link.Read(cursorData, sizeof(cursorData)) >= B_OK) {
cursor = fDesktop->GetCursorManager().CreateCursor(fClientTeam,
cursorData);
cursorData);
if (cursor == NULL)
status = B_NO_MEMORY;
}
@ -954,6 +954,27 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver& link)
fLink.Flush();
break;
}
case AS_REFERENCE_CURSOR:
{
STRACE(("ServerApp %s: Reference BCursor\n", Signature()));
// Attached data:
// 1) int32 token ID of the cursor to reference
int32 token;
if (link.Read<int32>(&token) != B_OK)
break;
if (!fDesktop->GetCursorManager().Lock())
break;
ServerCursor* cursor
= fDesktop->GetCursorManager().FindCursor(token);
if (cursor != NULL)
cursor->Acquire();
fDesktop->GetCursorManager().Unlock();
break;
}
case AS_DELETE_CURSOR:
{
STRACE(("ServerApp %s: Delete BCursor\n", Signature()));
@ -968,8 +989,9 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver& link)
if (!fDesktop->GetCursorManager().Lock())
break;
ServerCursor* cursor = fDesktop->GetCursorManager().FindCursor(token);
if (cursor) {
ServerCursor* cursor
= fDesktop->GetCursorManager().FindCursor(token);
if (cursor != NULL) {
if (pendingViewCursor)
cursor->SetPendingViewCursor(true);