2 // Copyright (c) 2014 Samsung Electronics Co., Ltd.
4 // Licensed under the Flora License, Version 1.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://floralicense.org/license/
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.
18 #include "lockless-buffer.h"
21 #include <dali/integration-api/debug.h>
29 LocklessBuffer::LocklessBuffer( size_t size )
33 // allocate memory to speed up operation
34 mBuffer[0] = new unsigned char[size];
35 mBuffer[1] = new unsigned char[size];
37 memset (mBuffer[0], 0, size );
38 memset (mBuffer[1], 0, size );
41 LocklessBuffer::~LocklessBuffer()
47 void LocklessBuffer::Write( const unsigned char *src, size_t size )
49 DALI_ASSERT_ALWAYS( size <= mSize );
52 BufferState currentState( __sync_fetch_and_or( &mState, WRITING ) );
53 DALI_ASSERT_DEBUG( !(currentState & WRITING_MASK) ); // WRITING bit should never be set when we get here
55 // copy data to current write buffer, negate state to get actual index (recap: R0W1 = 0, R1W0 = 1)
56 const unsigned int index = (currentState & WRITE_BUFFER_MASK);
57 memcpy( mBuffer[index], src, size );
59 // unset WRITING bit, set UPDATED bit
60 BufferState checkState = __sync_val_compare_and_swap( &mState,
61 static_cast<BufferState>(currentState | WRITING),
62 static_cast<BufferState>(index | UPDATED) );
64 DALI_ASSERT_DEBUG( checkState & WRITING );
65 (void)checkState; // Avoid unused variable warning
68 const unsigned char* LocklessBuffer::Read()
70 // current state (only to avoid multiple memory reads with volatile variable)
71 BufferState currentState( mState );
72 BufferState currentWriteBuf( static_cast<BufferState>( currentState & WRITE_BUFFER_MASK ) );
74 if( currentState & UPDATED_MASK )
76 // Try to swap buffers.
77 // This will set mState to 1 if readbuffer 0 was updated, 0 if readbuffer 1 was updated and fail if WRITING is set
78 if( __sync_bool_compare_and_swap( &mState,
79 static_cast<BufferState>(currentWriteBuf | UPDATED),
80 static_cast<BufferState>(!currentWriteBuf) ) )
83 return mBuffer[currentWriteBuf];
87 // UPDATE bit wasn't set or WRITING bit was set in other thread
88 // swap failed, read from current readbuffer
89 return mBuffer[!currentWriteBuf];
92 unsigned int LocklessBuffer::GetSize() const
94 return static_cast<unsigned int>(mSize);