Started implementing message passing by area. This will be needed for drag & drop messages and will probably be used for large messages instead of sending them through a port. Not yet finished and not enabled. Cleaned up a part of BLooper - this class should probably be cleaned up completely.

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@16459 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Michael Lotz 2006-02-18 12:29:05 +00:00
parent 7938b1158e
commit 721a0fe3e4
4 changed files with 317 additions and 136 deletions

View File

@ -269,6 +269,11 @@ class BMessage {
status_t _InitHeader();
status_t _Clear();
status_t _FlattenToArea(message_header **_header) const;
status_t _CopyForWrite();
status_t _Reference(message_header *header);
status_t _Dereference();
status_t _ResizeData(int32 offset, int32 change);
uint32 _HashName(const char* name) const;

View File

@ -20,6 +20,10 @@
#define MAX_ITEM_PREALLOCATION B_PAGE_SIZE
static const int32 kPortMessageCodeDirect = 'pjpp';
static const int32 kPortMessageCodeByArea = 'pjp2';
enum {
MESSAGE_FLAG_VALID = 0x0001,
MESSAGE_FLAG_REPLY_REQUIRED = 0x0002,
@ -27,7 +31,7 @@ enum {
MESSAGE_FLAG_IS_REPLY = 0x0008,
MESSAGE_FLAG_WAS_DELIVERED = 0x0010,
MESSAGE_FLAG_HAS_SPECIFIERS = 0x0020,
MESSAGE_FLAG_READ_ONLY = 0x0040
MESSAGE_FLAG_WAS_DROPPED = 0x0080
};
@ -61,6 +65,7 @@ struct BMessage::message_header {
int32 target;
int32 current_specifier;
area_id shared_area;
// reply info
port_id reply_port;
@ -168,6 +173,18 @@ class BMessage::Private {
return fMessage->_NativeFlatten(stream, size);
}
status_t
FlattenToArea(message_header **header) const
{
return fMessage->_FlattenToArea(header);
}
status_t
Reference(message_header *header)
{
return fMessage->_Reference(header);
}
status_t
SendMessage(port_id port, int32 token, bigtime_t timeout,
bool replyRequired, BMessenger &replyTo) const

View File

@ -1112,7 +1112,7 @@ void *
BLooper::ReadRawFromPort(int32 *msgCode, bigtime_t timeout)
{
PRINT(("BLooper::ReadRawFromPort()\n"));
int8 *msgBuffer = NULL;
uint8 *buffer = NULL;
ssize_t bufferSize;
do {
@ -1125,60 +1125,69 @@ BLooper::ReadRawFromPort(int32 *msgCode, bigtime_t timeout)
}
if (bufferSize > 0)
msgBuffer = new int8[bufferSize];
buffer = (uint8 *)malloc(bufferSize);
// we don't want to wait again here, since that can only mean
// that someone else has read our message and our bufferSize
// is now probably wrong
PRINT(("read_port()...\n"));
bufferSize = read_port_etc(fMsgPort, msgCode, msgBuffer, bufferSize,
B_RELATIVE_TIMEOUT, 0);
bufferSize = read_port_etc(fMsgPort, msgCode, buffer, bufferSize,
B_RELATIVE_TIMEOUT, 0);
if (bufferSize < B_OK) {
delete[] msgBuffer;
free(buffer);
return NULL;
}
PRINT(("BLooper::ReadRawFromPort() read: %.4s, %p\n", (char *)msgCode, msgBuffer));
return msgBuffer;
PRINT(("BLooper::ReadRawFromPort() read: %.4s, %p (%d bytes)\n", (char *)msgCode, buffer, bufferSize));
return buffer;
}
BMessage *
BLooper::ReadMessageFromPort(bigtime_t tout)
BLooper::ReadMessageFromPort(bigtime_t timeout)
{
PRINT(("BLooper::ReadMessageFromPort()\n"));
int32 msgcode;
BMessage* bmsg;
int32 msgCode;
BMessage *message = NULL;
void* msgbuffer = ReadRawFromPort(&msgcode, tout);
if (!msgbuffer)
void *buffer = ReadRawFromPort(&msgCode, timeout);
if (!buffer)
return NULL;
bmsg = ConvertToMessage(msgbuffer, msgcode);
message = ConvertToMessage(buffer, msgCode);
free(buffer);
delete[] (int8*)msgbuffer;
PRINT(("BLooper::ReadMessageFromPort() done: %p\n", bmsg));
return bmsg;
PRINT(("BLooper::ReadMessageFromPort() done: %p\n", message));
return message;
}
BMessage*
BLooper::ConvertToMessage(void* raw, int32 code)
BMessage *
BLooper::ConvertToMessage(void *buffer, int32 code)
{
PRINT(("BLooper::ConvertToMessage()\n"));
BMessage* bmsg = new BMessage(code);
if (!buffer)
return NULL;
if (raw != NULL) {
if (bmsg->Unflatten((const char*)raw) != B_OK) {
BMessage *message = new BMessage();
if (code == kPortMessageCodeByArea) {
BMessage::Private messagePrivate(message);
if (messagePrivate.Reference((BMessage::message_header *)buffer) != B_OK) {
PRINT(("BLooper::ConvertToMessage(): referencing message failed\n"));
delete message;
message = NULL;
}
} else {
if (message->Unflatten((const char *)buffer) != B_OK) {
PRINT(("BLooper::ConvertToMessage(): unflattening message failed\n"));
delete bmsg;
bmsg = NULL;
delete message;
message = NULL;
}
}
PRINT(("BLooper::ConvertToMessage(): %p\n", bmsg));
return bmsg;
PRINT(("BLooper::ConvertToMessage(): %p\n", message));
return message;
}

View File

@ -33,7 +33,8 @@
#include <string.h>
#define DEBUG_FUNCTION_ENTER //debug_printf("%ld: %s\n", __LINE__, __PRETTY_FUNCTION__);
#define DEBUG_FUNCTION_ENTER //debug_printf("thread: 0x%x; this: 0x%08x; header: 0x%08x; fields: 0x%08x; data: 0x%08x; line: %04ld; func: %s\n", find_thread(NULL), this, fHeader, fFields, fData, __LINE__, __PRETTY_FUNCTION__);
#define DEBUG_FUNCTION_ENTER2 //debug_printf("thread: 0x%x; line: %04ld: func: %s\n", find_thread(NULL), __LINE__, __PRETTY_FUNCTION__);
static const uint32 kMessageMagicR5 = 'FOB1';
@ -81,6 +82,7 @@ BMessage::BMessage(const BMessage &other)
{
DEBUG_FUNCTION_ENTER;
_InitCommon();
_InitHeader();
*this = other;
}
@ -99,6 +101,7 @@ BMessage &
BMessage::operator=(const BMessage &other)
{
DEBUG_FUNCTION_ENTER;
_Clear();
fHeader = (message_header *)malloc(sizeof(message_header));
@ -110,10 +113,11 @@ BMessage::operator=(const BMessage &other)
}
if (fHeader->data_size > 0) {
fData = (uint8 *)malloc(other.fHeader->data_size);
memcpy(fData, other.fData, other.fHeader->data_size);
fData = (uint8 *)malloc(fHeader->data_size);
memcpy(fData, other.fData, fHeader->data_size);
}
fHeader->shared_area = -1;
fHeader->fields_available = 0;
fHeader->data_available = 0;
what = fHeader->what;
@ -125,18 +129,19 @@ BMessage::operator=(const BMessage &other)
void *
BMessage::operator new(size_t size)
{
DEBUG_FUNCTION_ENTER;
DEBUG_FUNCTION_ENTER2;
if (!sMsgCache)
sMsgCache = new BBlockCache(10, size, B_OBJECT_CACHE);
return sMsgCache->Get(size);
void *pointer = sMsgCache->Get(size);
return pointer;
}
void *
BMessage::operator new(size_t, void *pointer)
{
DEBUG_FUNCTION_ENTER;
DEBUG_FUNCTION_ENTER2;
return pointer;
}
@ -144,7 +149,7 @@ BMessage::operator new(size_t, void *pointer)
void
BMessage::operator delete(void *pointer, size_t size)
{
DEBUG_FUNCTION_ENTER;
DEBUG_FUNCTION_ENTER2;
sMsgCache->Save(pointer, size);
}
@ -175,6 +180,7 @@ BMessage::_InitHeader()
fHeader->format = kMessageMagic4;
fHeader->flags = MESSAGE_FLAG_VALID;
fHeader->current_specifier = -1;
fHeader->shared_area = -1;
fHeader->target = B_NULL_TOKEN;
fHeader->reply_target = B_NULL_TOKEN;
@ -191,9 +197,9 @@ BMessage::_InitHeader()
status_t
BMessage::_Clear()
{
delete fOriginal;
fOriginal = NULL;
fQueueLink = NULL;
DEBUG_FUNCTION_ENTER;
if (fHeader && fHeader->shared_area >= B_OK)
_Dereference();
free(fHeader);
fHeader = NULL;
@ -202,6 +208,10 @@ BMessage::_Clear()
free(fData);
fData = NULL;
delete fOriginal;
fOriginal = NULL;
fQueueLink = NULL;
return B_OK;
}
@ -524,6 +534,9 @@ BMessage::Rename(const char *oldEntry, const char *newEntry)
if (!oldEntry || !newEntry)
return B_BAD_VALUE;
if (fHeader->shared_area >= B_OK)
_CopyForWrite();
uint32 hash = _HashName(oldEntry) % fHeader->hash_table_size;
int32 *nextField = &fHeader->hash_table[hash];
@ -604,8 +617,7 @@ BMessage::Previous() const
DEBUG_FUNCTION_ENTER;
/* ToDo: test if the "_previous_" field is used in R5 */
if (!fOriginal) {
delete fOriginal;
fOriginal = new BMessage;
fOriginal = new BMessage();
if (FindMessage("_previous_", fOriginal) != B_OK) {
delete fOriginal;
@ -621,7 +633,7 @@ bool
BMessage::WasDropped() const
{
DEBUG_FUNCTION_ENTER;
return fHeader->flags & MESSAGE_FLAG_READ_ONLY;
return fHeader->flags & MESSAGE_FLAG_WAS_DROPPED;
}
@ -752,7 +764,6 @@ ssize_t
BMessage::FlattenedSize() const
{
DEBUG_FUNCTION_ENTER;
//return _NativeFlattenedSize();
return BPrivate::r5_message_flattened_size(this);
}
@ -761,7 +772,6 @@ status_t
BMessage::Flatten(char *buffer, ssize_t size) const
{
DEBUG_FUNCTION_ENTER;
//return _NativeFlatten(buffer, size);
return BPrivate::flatten_r5_message(this, buffer, size);
}
@ -770,7 +780,6 @@ status_t
BMessage::Flatten(BDataIO *stream, ssize_t *size) const
{
DEBUG_FUNCTION_ENTER;
//return _NativeFlatten(stream, size);
return BPrivate::flatten_r5_message(this, stream, size);
}
@ -883,7 +892,8 @@ BMessage::Unflatten(const char *flatBuffer)
// native message unflattening
free(fHeader);
_Clear();
fHeader = (message_header *)malloc(sizeof(message_header));
if (!fHeader)
return B_NO_MEMORY;
@ -891,6 +901,11 @@ BMessage::Unflatten(const char *flatBuffer)
memcpy(fHeader, flatBuffer, sizeof(message_header));
flatBuffer += sizeof(message_header);
fHeader->shared_area = -1;
fHeader->fields_available = 0;
fHeader->data_available = 0;
what = fHeader->what;
/* ToDo: better message validation (checksum) */
if (fHeader->format != kMessageMagic4 ||
!(fHeader->flags & MESSAGE_FLAG_VALID)) {
@ -899,8 +914,6 @@ BMessage::Unflatten(const char *flatBuffer)
return B_BAD_VALUE;
}
free(fFields);
fFields = NULL;
if (fHeader->fields_size > 0) {
fFields = (field_header *)malloc(fHeader->fields_size);
if (!fFields)
@ -910,8 +923,6 @@ BMessage::Unflatten(const char *flatBuffer)
flatBuffer += fHeader->fields_size;
}
free(fData);
fData = NULL;
if (fHeader->data_size > 0) {
fData = (uint8 *)malloc(fHeader->data_size);
if (!fData)
@ -920,9 +931,6 @@ BMessage::Unflatten(const char *flatBuffer)
memcpy(fData, flatBuffer, fHeader->data_size);
}
fHeader->fields_available = 0;
fHeader->data_available = 0;
what = fHeader->what;
return B_OK;
}
@ -948,7 +956,8 @@ BMessage::Unflatten(BDataIO *stream)
// native message unflattening
free(fHeader);
_Clear();
fHeader = (message_header *)malloc(sizeof(message_header));
if (!fHeader)
return B_NO_MEMORY;
@ -957,6 +966,12 @@ BMessage::Unflatten(BDataIO *stream)
uint8 *header = (uint8 *)fHeader;
ssize_t result = stream->Read(header + sizeof(uint32),
sizeof(message_header) - sizeof(uint32));
fHeader->shared_area = -1;
fHeader->fields_available = 0;
fHeader->data_available = 0;
what = fHeader->what;
if (result != sizeof(message_header) - sizeof(uint32)) {
_Clear();
_InitHeader();
@ -971,8 +986,6 @@ BMessage::Unflatten(BDataIO *stream)
return B_BAD_VALUE;
}
free(fFields);
fFields = NULL;
if (fHeader->fields_size > 0) {
fFields = (field_header *)malloc(fHeader->fields_size);
if (!fFields)
@ -986,8 +999,6 @@ BMessage::Unflatten(BDataIO *stream)
}
}
free(fData);
fData = NULL;
if (fHeader->data_size > 0) {
fData = (uint8 *)malloc(fHeader->data_size);
if (!fData)
@ -1001,9 +1012,6 @@ BMessage::Unflatten(BDataIO *stream)
}
}
fHeader->fields_available = 0;
fHeader->data_available = 0;
what = fHeader->what;
return B_OK;
}
@ -1166,6 +1174,157 @@ BMessage::PopSpecifier()
}
/* The concept of message sending by area:
The traditional way of sending a message is to send it by flattening it to
a buffer, pushing it through a port, reading it into the outputbuffer and
unflattening it from there (copying the data again). While this works ok
for small messages it does not make any sense for larger ones and may even
hit some port capacity limit.
Often in the life of a BMessage, it will be sent to someone. Almost as
often the one receiving the message will not need to change the message
in any way, but uses it "read only" to get information from it. This means
that all that copying is pretty pointless in the first place since we
could simply pass the original buffers on.
It's obviously not exactly as simple as this, since we cannot just use the
memory of one application in another - but we can share areas with
eachother.
Therefore instead of flattening into a buffer, we copy the message data
into an area, put this information into the message header and only push
this through the port. The receiving looper then builds a BMessage from
the header, that only references the data in the area (not copying it),
allowing read only access to it.
Only if write access is necessary the message will be copyed from the area
to its own buffers (like in the unflatten step before).
The double copying is reduced to a single copy in most cases and we safe
the possibly dangerous and slower route of moving the data through a port.
Additionally we save us the reference counting with the use of areas that
are reference counted internally. So we don't have to worry about leaving
an area behind or deleting one that is still in use.
*/
status_t
BMessage::_FlattenToArea(message_header **_header) const
{
DEBUG_FUNCTION_ENTER;
message_header *header = (message_header *)malloc(sizeof(message_header));
memcpy(header, fHeader, sizeof(message_header));
*_header = header;
if (header->shared_area >= B_OK)
return B_OK;
if (header->fields_size == 0 && header->data_size == 0)
return B_OK;
uint8 *address = NULL;
ssize_t size = sizeof(int32) + header->fields_size + header->data_size;
size = ((size + B_PAGE_SIZE) & ~(B_PAGE_SIZE - 1)) + B_PAGE_SIZE;
area_id area = create_area("Shared BMessage data", (void **)&address,
B_ANY_ADDRESS, size, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA);
if (area < B_OK) {
free(header);
*_header = NULL;
return area;
}
if (header->fields_size > 0) {
memcpy(address, fFields, header->fields_size);
address += header->fields_size;
}
if (header->data_size > 0)
memcpy(address, fData, header->data_size);
header->shared_area = area;
header->fields_available = 0;
header->data_available = 0;
return B_OK;
}
status_t
BMessage::_CopyForWrite()
{
DEBUG_FUNCTION_ENTER;
if (fHeader->shared_area < B_OK)
return B_OK;
field_header *newFields = NULL;
uint8 *newData = NULL;
if (fHeader->fields_size > 0) {
newFields = (field_header *)malloc(fHeader->fields_size);
memcpy(newFields, fFields, fHeader->fields_size);
}
if (fHeader->data_size > 0) {
newData = (uint8 *)malloc(fHeader->data_size);
memcpy(newData, fData, fHeader->data_size);
}
_Dereference();
fHeader->fields_available = 0;
fHeader->data_available = 0;
fFields = newFields;
fData = newData;
return B_OK;
}
status_t
BMessage::_Reference(message_header *header)
{
DEBUG_FUNCTION_ENTER;
_Clear();
fHeader = (message_header *)malloc(sizeof(message_header));
memcpy(fHeader, header, sizeof(message_header));
fHeader->fields_available = 0;
fHeader->data_available = 0;
what = fHeader->what;
if (fHeader->shared_area < B_OK) {
if (fHeader->fields_size == 0 && header->data_size == 0)
return B_OK;
_InitHeader();
return B_BAD_DATA;
}
uint8 *address = NULL;
area_id clone = clone_area("Cloned BMessage data", (void **)&address,
B_ANY_ADDRESS, B_READ_AREA, fHeader->shared_area);
if (clone < B_OK) {
_InitHeader();
return clone;
}
fHeader->shared_area = clone;
fFields = (field_header *)address;
address += fHeader->fields_size;
fData = address;
return B_OK;
}
status_t
BMessage::_Dereference()
{
DEBUG_FUNCTION_ENTER;
delete_area(fHeader->shared_area);
fHeader->shared_area = -1;
fFields = NULL;
fData = NULL;
return B_OK;
}
status_t
BMessage::_ResizeData(int32 offset, int32 change)
{
@ -1377,6 +1536,9 @@ BMessage::AddData(const char *name, type_code type, const void *data,
if (numBytes <= 0 || !data)
return B_BAD_VALUE;
if (fHeader->shared_area >= B_OK)
_CopyForWrite();
field_header *field = NULL;
status_t result = _FindField(name, type, &field);
if (result == B_NAME_NOT_FOUND)
@ -1428,6 +1590,9 @@ BMessage::RemoveData(const char *name, int32 index)
if (index >= field->count)
return B_BAD_INDEX;
if (fHeader->shared_area >= B_OK)
_CopyForWrite();
if (field->count == 1)
return _RemoveField(field);
@ -1467,6 +1632,9 @@ BMessage::RemoveName(const char *name)
if (!field)
return B_ERROR;
if (fHeader->shared_area >= B_OK)
_CopyForWrite();
return _RemoveField(field);
}
@ -1475,23 +1643,8 @@ status_t
BMessage::MakeEmpty()
{
DEBUG_FUNCTION_ENTER;
free(fFields);
fFields = NULL;
free(fData);
fData = NULL;
fHeader->fields_size = 0;
fHeader->data_size = 0;
fHeader->fields_available = 0;
fHeader->data_available = 0;
fHeader->current_specifier = -1;
fHeader->field_count = 0;
fHeader->flags &= ~MESSAGE_FLAG_HAS_SPECIFIERS;
// initializing the hash table to -1 because 0 is a valid index
memset(&fHeader->hash_table, 255, sizeof(fHeader->hash_table));
_Clear();
_InitHeader();
return B_OK;
}
@ -1554,6 +1707,9 @@ BMessage::ReplaceData(const char *name, type_code type, int32 index,
if (index >= field->count)
return B_BAD_INDEX;
if (fHeader->shared_area >= B_OK)
_CopyForWrite();
if (field->flags & FIELD_FLAG_FIXED_SIZE) {
ssize_t size = field->data_size / field->count;
if (size != numBytes)
@ -1606,7 +1762,7 @@ BMessage::HasData(const char *name, type_code type, int32 index) const
void
BMessage::_StaticInit()
{
DEBUG_FUNCTION_ENTER;
DEBUG_FUNCTION_ENTER2;
sReplyPorts[0] = create_port(1, "tmp_rport0");
sReplyPorts[1] = create_port(1, "tmp_rport1");
sReplyPorts[2] = create_port(1, "tmp_rport2");
@ -1622,7 +1778,7 @@ BMessage::_StaticInit()
void
BMessage::_StaticCleanup()
{
DEBUG_FUNCTION_ENTER;
DEBUG_FUNCTION_ENTER2;
delete_port(sReplyPorts[0]);
sReplyPorts[0] = -1;
delete_port(sReplyPorts[1]);
@ -1635,7 +1791,7 @@ BMessage::_StaticCleanup()
void
BMessage::_StaticCacheCleanup()
{
DEBUG_FUNCTION_ENTER;
DEBUG_FUNCTION_ENTER2;
delete sMsgCache;
sMsgCache = NULL;
}
@ -1644,7 +1800,7 @@ BMessage::_StaticCacheCleanup()
int32
BMessage::_StaticGetCachedReplyPort()
{
DEBUG_FUNCTION_ENTER;
DEBUG_FUNCTION_ENTER2;
int index = -1;
for (int32 i = 0; i < sNumReplyPorts; i++) {
int32 old = atomic_add(&(sReplyPortInUse[i]), 1);
@ -1667,11 +1823,27 @@ BMessage::_SendMessage(port_id port, int32 token, bigtime_t timeout,
bool replyRequired, BMessenger &replyTo) const
{
DEBUG_FUNCTION_ENTER;
uint32 oldFlags = fHeader->flags;
int32 oldTarget = fHeader->target;
port_id oldReplyPort = fHeader->reply_port;
int32 oldReplyTarget = fHeader->reply_target;
team_id oldReplyTeam = fHeader->reply_team;
ssize_t size = 0;
char *buffer = NULL;
message_header *header = NULL;
status_t result;
int32 code;
if (/*fHeader->fields_size + fHeader->data_size > B_PAGE_SIZE*/false) {
result = _FlattenToArea(&header);
buffer = (char *)header;
size = sizeof(message_header);
code = kPortMessageCodeByArea;
} else {
size = _NativeFlattenedSize();
buffer = (char *)malloc(size);
result = _NativeFlatten(buffer, size);
header = (message_header *)buffer;
code = kPortMessageCodeDirect;
}
if (result < B_OK)
return result;
if (!replyTo.IsValid()) {
BMessenger::Private(replyTo).SetTo(fHeader->reply_team,
@ -1684,50 +1856,22 @@ BMessage::_SendMessage(port_id port, int32 token, bigtime_t timeout,
BMessenger::Private replyToPrivate(replyTo);
if (replyRequired)
fHeader->flags |= MESSAGE_FLAG_REPLY_REQUIRED;
header->flags |= MESSAGE_FLAG_REPLY_REQUIRED;
else
fHeader->flags &= ~MESSAGE_FLAG_REPLY_REQUIRED;
header->flags &= ~MESSAGE_FLAG_REPLY_REQUIRED;
fHeader->target = token;
fHeader->reply_team = replyToPrivate.Team();
fHeader->reply_port = replyToPrivate.Port();
fHeader->reply_target = replyToPrivate.Token();
fHeader->flags |= MESSAGE_FLAG_WAS_DELIVERED;
/* ToDo: we can use _kern_writev_port to send the three parts directly:
iovec vectors[3];
vectors[0].iov_base = fHeader;
vectors[0].iov_len = sizeof(message_header);
vectors[1].iov_base = fFields;
vectors[1].iov_len = fHeader->fields_size;
vectors[2].iov_base = fData;
vectors[2].iov_len = fHeader->data_size;
status_t result;
do {
result = _kern_writev_port_etc(port, 'pjpp', vectors, 3,
_NativeFlattenedSize(), B_RELATIVE_TIMEOUT, timeout);
} while (result == B_INTERRUPTED);
*/
ssize_t size = _NativeFlattenedSize();
char *buffer = new char[size];
status_t result = _NativeFlatten(buffer, size);
if (result < B_OK)
goto error;
header->target = token;
header->reply_team = replyToPrivate.Team();
header->reply_port = replyToPrivate.Port();
header->reply_target = replyToPrivate.Token();
header->flags |= MESSAGE_FLAG_WAS_DELIVERED;
do {
result = write_port_etc(port, 'pjpp', buffer, size,
result = write_port_etc(port, code, (void *)buffer, size,
B_RELATIVE_TIMEOUT, timeout);
} while (result == B_INTERRUPTED);
error:
fHeader->flags = oldFlags;
fHeader->target = oldTarget;
fHeader->reply_port = oldReplyPort;
fHeader->reply_target = oldReplyTarget;
fHeader->reply_team = oldReplyTeam;
delete[] buffer;
free(buffer);
return result;
}
@ -1803,11 +1947,11 @@ status_t
BMessage::_SendFlattenedMessage(void *data, int32 size, port_id port,
int32 token, bigtime_t timeout)
{
DEBUG_FUNCTION_ENTER;
DEBUG_FUNCTION_ENTER2;
if (!data)
return B_BAD_VALUE;
uint32 magic = *(uint32*)data;
uint32 magic = *(uint32 *)data;
if (magic == kMessageMagic4 || magic == kMessageMagic4Swapped) {
message_header *header = (message_header *)data;
@ -1829,8 +1973,8 @@ BMessage::_SendFlattenedMessage(void *data, int32 size, port_id port,
status_t result;
do {
result = write_port_etc(port, 'pjpp', data, size, B_RELATIVE_TIMEOUT,
timeout);
result = write_port_etc(port, kPortMessageCodeDirect, data, size,
B_RELATIVE_TIMEOUT, timeout);
} while (result == B_INTERRUPTED);
return result;
@ -1841,7 +1985,7 @@ static status_t
handle_reply(port_id replyPort, int32 *pCode, bigtime_t timeout,
BMessage *reply)
{
DEBUG_FUNCTION_ENTER;
DEBUG_FUNCTION_ENTER2;
status_t result;
do {
result = port_buffer_size_etc(replyPort, B_RELATIVE_TIMEOUT, timeout);
@ -1851,19 +1995,25 @@ handle_reply(port_id replyPort, int32 *pCode, bigtime_t timeout,
return result;
// The API lied. It really isn't an error code, but the message size...
char *buffer = new char[result];
char *buffer = (char *)malloc(result);
do {
result = read_port(replyPort, pCode, buffer, result);
} while (result == B_INTERRUPTED);
if (result < B_OK || *pCode != 'pjpp') {
delete[] buffer;
if (result < B_OK || (*pCode != kPortMessageCodeDirect
&& *pCode != kPortMessageCodeByArea)) {
free(buffer);
return (result < B_OK ? result : B_ERROR);
}
result = reply->Unflatten(buffer);
delete[] buffer;
if (*pCode == kPortMessageCodeDirect) {
result = reply->Unflatten(buffer);
} else if (*pCode == kPortMessageCodeByArea) {
BMessage::Private messagePrivate(reply);
result = messagePrivate.Reference((BMessage::message_header *)buffer);
}
free(buffer);
return result;
}
@ -1871,7 +2021,7 @@ handle_reply(port_id replyPort, int32 *pCode, bigtime_t timeout,
static status_t
convert_message(const KMessage *fromMessage, BMessage *toMessage)
{
DEBUG_FUNCTION_ENTER;
DEBUG_FUNCTION_ENTER2;
if (!fromMessage || !toMessage)
return B_BAD_VALUE;
@ -2083,10 +2233,10 @@ BMessage::AddMessage(const char *name, const BMessage *message)
copying an extra buffer. Functions can be added that return a direct
pointer into the message. */
ssize_t size = message->FlattenedSize();
ssize_t size = message->_NativeFlattenedSize();
char buffer[size];
status_t error = message->Flatten(buffer, size);
status_t error = message->_NativeFlatten(buffer, size);
if (error >= B_OK)
error = AddData(name, B_MESSAGE_TYPE, &buffer, size, false);