License conversion from Flora to Apache 2.0
[platform/core/uifw/dali-core.git] / dali / internal / common / message-buffer.cpp
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
19 #include <dali/internal/common/message-buffer.h>
20
21 // EXTERNAL INCLUDES
22 #include <limits>
23 #include <cstdlib>
24
25 // INTERNAL INCLUDES
26 #include <dali/integration-api/debug.h>
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(unsigned int) - 1u; // For word alignment on ARM
41
42 } // unnamed namespace
43
44 namespace Dali
45 {
46
47 namespace Internal
48 {
49
50 MessageBuffer::MessageBuffer( std::size_t initialCapacity )
51 : mInitialCapacity( initialCapacity / sizeof(unsigned int) ),
52   mData( NULL ),
53   mNextSlot( NULL ),
54   mCapacity( 0 ),
55   mSize( 0 )
56 {
57 }
58
59 MessageBuffer::~MessageBuffer()
60 {
61   free( mData );
62 }
63
64 unsigned int* MessageBuffer::ReserveMessageSlot( std::size_t size )
65 {
66   DALI_ASSERT_DEBUG( 0 != size );
67
68   std::size_t requestedSize = (size + MAX_DIVISION_BY_WORD_REMAINDER) / sizeof(unsigned int);
69   std::size_t requiredSize = requestedSize + MESSAGE_SIZE_PLUS_END_FIELD;
70
71   // Keep doubling the additional capacity until we have enough
72   std::size_t nextCapacity = mCapacity ? mCapacity : mInitialCapacity;
73
74   if ( (nextCapacity - mSize) < requiredSize )
75   {
76     nextCapacity = nextCapacity * INCREMENT_NUMERATOR / INCREMENT_DENOMINATOR;
77
78     // Something has gone badly wrong if requiredSize is this big
79     DALI_ASSERT_DEBUG( (nextCapacity - mSize) > requiredSize );
80   }
81
82   if ( nextCapacity > mCapacity )
83   {
84     IncreaseCapacity( nextCapacity );
85   }
86
87   // Now reserve the slot
88   unsigned int* slot = mNextSlot;
89
90   *slot++ = requestedSize; // Object size marker is stored in first word
91
92   mSize += requestedSize + MESSAGE_SIZE_FIELD;
93   mNextSlot = mData + mSize;
94
95   // End marker
96   *mNextSlot = 0;
97
98   return slot;
99 }
100
101 std::size_t MessageBuffer::GetCapacity() const
102 {
103   return mCapacity * sizeof(unsigned int);
104 }
105
106 MessageBuffer::Iterator MessageBuffer::Begin() const
107 {
108   if ( 0 != mSize )
109   {
110     return Iterator( mData );
111   }
112
113   return Iterator( NULL );
114 }
115
116 void MessageBuffer::Reset()
117 {
118   // All messages have been processed, reset the buffer
119   mSize = 0;
120   mNextSlot = mData;
121 }
122
123 void MessageBuffer::IncreaseCapacity( std::size_t newCapacity )
124 {
125   DALI_ASSERT_DEBUG( newCapacity > mCapacity );
126
127   if ( mData )
128   {
129     // Often this avoids the need to copy memory
130     mData = reinterpret_cast<unsigned int*>( realloc( mData, newCapacity * sizeof(unsigned int) ) );
131   }
132   else
133   {
134     mData = reinterpret_cast<unsigned int*>( malloc( newCapacity * sizeof(unsigned int) ) );
135   }
136   DALI_ASSERT_ALWAYS( NULL != mData );
137
138   mCapacity = newCapacity;
139   mNextSlot = mData + mSize;
140 }
141
142 MessageBuffer::Iterator::Iterator(unsigned int* current)
143 : mCurrent(current),
144   mMessageSize(0)
145 {
146   if( NULL != mCurrent )
147   {
148     // The first word is the size of the following object
149     mMessageSize = *mCurrent++;
150   }
151 }
152
153 MessageBuffer::Iterator::Iterator(const Iterator& copy)
154 : mCurrent( copy.mCurrent ),
155   mMessageSize( copy.mMessageSize )
156 {
157 }
158
159 } // namespace Internal
160
161 } // namespace Dali