2 * Copyright (c) 2014 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include <dali/internal/common/message-buffer.h>
26 #include <dali/integration-api/debug.h>
28 namespace // unnamed namespace
31 // Increase capacity by 1.5 when buffer limit reached
32 const unsigned int INCREMENT_NUMERATOR = 3u;
33 const unsigned int INCREMENT_DENOMINATOR = 2u;
35 const unsigned int MESSAGE_SIZE_FIELD = 1u; // Size required to mark the message size
36 const unsigned int MESSAGE_END_FIELD = 1u; // Size required to mark the end of messages
38 const unsigned int MESSAGE_SIZE_PLUS_END_FIELD = MESSAGE_SIZE_FIELD + MESSAGE_END_FIELD;
40 const unsigned int MAX_DIVISION_BY_WORD_REMAINDER = sizeof(Dali::Internal::MessageBuffer::WordType) - 1u; // For word alignment on ARM
41 const unsigned int WORD_SIZE = sizeof(Dali::Internal::MessageBuffer::WordType);
43 } // unnamed namespace
51 MessageBuffer::MessageBuffer( std::size_t initialCapacity )
52 : mInitialCapacity( initialCapacity / WORD_SIZE ),
60 MessageBuffer::~MessageBuffer()
65 unsigned int* MessageBuffer::ReserveMessageSlot( std::size_t size )
67 DALI_ASSERT_DEBUG( 0 != size );
69 // Number of aligned words required to handle a message of size in bytes
70 std::size_t requestedSize = (size + MAX_DIVISION_BY_WORD_REMAINDER) / WORD_SIZE;
71 std::size_t requiredSize = requestedSize + MESSAGE_SIZE_PLUS_END_FIELD;
73 // Keep doubling the additional capacity until we have enough
74 std::size_t nextCapacity = mCapacity ? mCapacity : mInitialCapacity;
76 if ( (nextCapacity - mSize) < requiredSize )
78 nextCapacity = nextCapacity * INCREMENT_NUMERATOR / INCREMENT_DENOMINATOR;
80 // Something has gone badly wrong if requiredSize is this big
81 DALI_ASSERT_DEBUG( (nextCapacity - mSize) > requiredSize );
84 if ( nextCapacity > mCapacity )
86 IncreaseCapacity( nextCapacity );
89 // Now reserve the slot
90 WordType* slot = mNextSlot;
92 *slot++ = requestedSize; // Object size marker is stored in first word
94 mSize += requestedSize + MESSAGE_SIZE_FIELD;
95 mNextSlot = mData + mSize;
100 return reinterpret_cast<unsigned int*>(slot);
103 std::size_t MessageBuffer::GetCapacity() const
105 return mCapacity * WORD_SIZE;
108 MessageBuffer::Iterator MessageBuffer::Begin() const
112 return Iterator( mData );
115 return Iterator( NULL );
118 void MessageBuffer::Reset()
120 // All messages have been processed, reset the buffer
125 void MessageBuffer::IncreaseCapacity( std::size_t newCapacity )
127 DALI_ASSERT_DEBUG( newCapacity > mCapacity );
131 // Often this avoids the need to copy memory
133 WordType* oldData = mData;
134 mData = reinterpret_cast<WordType*>( realloc( mData, newCapacity * WORD_SIZE ) );
136 // if realloc fails the old data is still valid
139 // TODO: Process message queue to free up some data?
141 DALI_ASSERT_DEBUG( false && "Realloc failed we're out of memory!" );
146 mData = reinterpret_cast<WordType*>( malloc( newCapacity * WORD_SIZE ) );
148 DALI_ASSERT_ALWAYS( NULL != mData );
150 mCapacity = newCapacity;
151 mNextSlot = mData + mSize;
154 MessageBuffer::Iterator::Iterator(WordType* current)
158 if( NULL != mCurrent )
160 // The first word is the size of the following object
161 mMessageSize = *mCurrent++;
165 MessageBuffer::Iterator::Iterator(const Iterator& copy)
166 : mCurrent( copy.mCurrent ),
167 mMessageSize( copy.mMessageSize )
171 } // namespace Internal