Dali 3D User Interface Engine
message-buffer.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2014 Samsung Electronics Co., Ltd.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  *
16  */
17 
18 // CLASS HEADER
20 
21 // EXTERNAL INCLUDES
22 #include <limits>
23 #include <cstdlib>
24 
25 // INTERNAL INCLUDES
27 
28 namespace // unnamed namespace
29 {
30 
31 // Increase capacity by 1.5 when buffer limit reached
32 const unsigned int INCREMENT_NUMERATOR = 3u;
33 const unsigned int INCREMENT_DENOMINATOR = 2u;
34 
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
37 
38 const unsigned int MESSAGE_SIZE_PLUS_END_FIELD = MESSAGE_SIZE_FIELD + MESSAGE_END_FIELD;
39 
40 const unsigned int MAX_DIVISION_BY_WORD_REMAINDER = sizeof(Dali::Internal::MessageBuffer::WordType) - 1u; // For word alignment on ARM
42 
43 } // unnamed namespace
44 
45 namespace Dali
46 {
47 
48 namespace Internal
49 {
50 
51 MessageBuffer::MessageBuffer( std::size_t initialCapacity )
52 : mInitialCapacity( initialCapacity / WORD_SIZE ),
53  mData( NULL ),
54  mNextSlot( NULL ),
55  mCapacity( 0 ),
56  mSize( 0 )
57 {
58 }
59 
61 {
62  free( mData );
63 }
64 
65 unsigned int* MessageBuffer::ReserveMessageSlot( std::size_t size )
66 {
67  DALI_ASSERT_DEBUG( 0 != size );
68 
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;
72 
73  // Keep doubling the additional capacity until we have enough
74  std::size_t nextCapacity = mCapacity ? mCapacity : mInitialCapacity;
75 
76  if ( (nextCapacity - mSize) < requiredSize )
77  {
78  nextCapacity = nextCapacity * INCREMENT_NUMERATOR / INCREMENT_DENOMINATOR;
79 
80  // Something has gone badly wrong if requiredSize is this big
81  DALI_ASSERT_DEBUG( (nextCapacity - mSize) > requiredSize );
82  }
83 
84  if ( nextCapacity > mCapacity )
85  {
86  IncreaseCapacity( nextCapacity );
87  }
88 
89  // Now reserve the slot
90  WordType* slot = mNextSlot;
91 
92  *slot++ = requestedSize; // Object size marker is stored in first word
93 
94  mSize += requestedSize + MESSAGE_SIZE_FIELD;
95  mNextSlot = mData + mSize;
96 
97  // End marker
98  *mNextSlot = 0;
99 
100  return reinterpret_cast<unsigned int*>(slot);
101 }
102 
103 std::size_t MessageBuffer::GetCapacity() const
104 {
105  return mCapacity * WORD_SIZE;
106 }
107 
109 {
110  if ( 0 != mSize )
111  {
112  return Iterator( mData );
113  }
114 
115  return Iterator( NULL );
116 }
117 
119 {
120  // All messages have been processed, reset the buffer
121  mSize = 0;
122  mNextSlot = mData;
123 }
124 
125 void MessageBuffer::IncreaseCapacity( std::size_t newCapacity )
126 {
127  DALI_ASSERT_DEBUG( newCapacity > mCapacity );
128 
129  if ( mData )
130  {
131  // Often this avoids the need to copy memory
132 
133  WordType* oldData = mData;
134  mData = reinterpret_cast<WordType*>( realloc( mData, newCapacity * WORD_SIZE ) );
135 
136  // if realloc fails the old data is still valid
137  if( !mData )
138  {
139  // TODO: Process message queue to free up some data?
140  free(oldData);
141  DALI_ASSERT_DEBUG( false && "Realloc failed we're out of memory!" );
142  }
143  }
144  else
145  {
146  mData = reinterpret_cast<WordType*>( malloc( newCapacity * WORD_SIZE ) );
147  }
148  DALI_ASSERT_ALWAYS( NULL != mData );
149 
150  mCapacity = newCapacity;
151  mNextSlot = mData + mSize;
152 }
153 
155 : mCurrent(current),
156  mMessageSize(0)
157 {
158  if( NULL != mCurrent )
159  {
160  // The first word is the size of the following object
161  mMessageSize = *mCurrent++;
162  }
163 }
164 
166 : mCurrent( copy.mCurrent ),
167  mMessageSize( copy.mMessageSize )
168 {
169 }
170 
171 } // namespace Internal
172 
173 } // namespace Dali
Dali Docs Home
Read more about Dali