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 "lockless-buffer.h"
22 #include <dali/integration-api/debug.h>
30 LocklessBuffer::LocklessBuffer( size_t size )
34 // allocate memory to speed up operation
35 mBuffer[0] = new unsigned char[size];
36 mBuffer[1] = new unsigned char[size];
38 memset (mBuffer[0], 0, size );
39 memset (mBuffer[1], 0, size );
42 LocklessBuffer::~LocklessBuffer()
48 void LocklessBuffer::Write( const unsigned char *src, size_t size )
50 DALI_ASSERT_ALWAYS( size <= mSize );
53 BufferState currentState( std::atomic_fetch_or( &mState, WRITING ) );
55 DALI_ASSERT_DEBUG( !(currentState & WRITING_MASK) ); // WRITING bit should never be set when we get here
57 // copy data to current write buffer, negate state to get actual index (recap: R0W1 = 0, R1W0 = 1)
58 const unsigned int index = (currentState & WRITE_BUFFER_MASK);
59 memcpy( mBuffer[index], src, size );
61 // unset WRITING bit, set UPDATED bit
62 BufferState writingState = static_cast<BufferState>(currentState | WRITING);
63 BufferState checkState = mState;
64 mState.compare_exchange_strong( writingState, static_cast<BufferState>(index | UPDATED) );
66 DALI_ASSERT_DEBUG( checkState & WRITING );
67 (void)checkState; // Avoid unused variable warning
70 const unsigned char* LocklessBuffer::Read()
72 // current state (only to avoid multiple memory reads with volatile variable)
73 BufferState currentState( mState );
74 BufferState currentWriteBuf( static_cast<BufferState>( currentState & WRITE_BUFFER_MASK ) );
76 if( currentState & UPDATED_MASK )
78 // Try to swap buffers.
79 // This will set mState to 1 if readbuffer 0 was updated, 0 if readbuffer 1 was updated and fail if WRITING is set
80 BufferState writingState = static_cast<BufferState>(currentWriteBuf | UPDATED);
81 if( mState.compare_exchange_strong( writingState, static_cast<BufferState>(!currentWriteBuf) ) )
84 return mBuffer[currentWriteBuf];
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];
93 unsigned int LocklessBuffer::GetSize() const
95 return static_cast<unsigned int>(mSize);