Dali 3D User Interface Engine
lockless-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
19 #include "lockless-buffer.h"
20 
21 // INTERNAL INCLUDES
23 
24 namespace Dali
25 {
26 
27 namespace Integration
28 {
29 
31 : mState( R0W1 ),
32  mSize( size )
33 {
34  // allocate memory to speed up operation
35  mBuffer[0] = new unsigned char[size];
36  mBuffer[1] = new unsigned char[size];
37 
38  memset (mBuffer[0], 0, size );
39  memset (mBuffer[1], 0, size );
40 }
41 
43 {
44  delete[] mBuffer[0];
45  delete[] mBuffer[1];
46 }
47 
48 void LocklessBuffer::Write( const unsigned char *src, size_t size )
49 {
50  DALI_ASSERT_ALWAYS( size <= mSize );
51 
52  // set WRITING bit
53  BufferState currentState( __sync_fetch_and_or( &mState, WRITING ) );
54  DALI_ASSERT_DEBUG( !(currentState & WRITING_MASK) ); // WRITING bit should never be set when we get here
55 
56  // copy data to current write buffer, negate state to get actual index (recap: R0W1 = 0, R1W0 = 1)
57  const unsigned int index = (currentState & WRITE_BUFFER_MASK);
58  memcpy( mBuffer[index], src, size );
59 
60  // unset WRITING bit, set UPDATED bit
61  BufferState checkState = __sync_val_compare_and_swap( &mState,
62  static_cast<BufferState>(currentState | WRITING),
63  static_cast<BufferState>(index | UPDATED) );
64 
65  DALI_ASSERT_DEBUG( checkState & WRITING );
66  (void)checkState; // Avoid unused variable warning
67 }
68 
69 const unsigned char* LocklessBuffer::Read()
70 {
71  // current state (only to avoid multiple memory reads with volatile variable)
72  BufferState currentState( mState );
73  BufferState currentWriteBuf( static_cast<BufferState>( currentState & WRITE_BUFFER_MASK ) );
74 
75  if( currentState & UPDATED_MASK )
76  {
77  // Try to swap buffers.
78  // This will set mState to 1 if readbuffer 0 was updated, 0 if readbuffer 1 was updated and fail if WRITING is set
79  if( __sync_bool_compare_and_swap( &mState,
80  static_cast<BufferState>(currentWriteBuf | UPDATED),
81  static_cast<BufferState>(!currentWriteBuf) ) )
82  {
83  // swap successful
84  return mBuffer[currentWriteBuf];
85  }
86  }
87 
88  // UPDATE bit wasn't set or WRITING bit was set in other thread
89  // swap failed, read from current readbuffer
90  return mBuffer[!currentWriteBuf];
91 }
92 
93 unsigned int LocklessBuffer::GetSize() const
94 {
95  return static_cast<unsigned int>(mSize);
96 }
97 
98 } // Internal
99 
100 } // Dali
Dali Docs Home
Read more about Dali