2 * Copyright (c) 2020 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>
28 LocklessBuffer::LocklessBuffer(uint32_t size)
32 // allocate memory to speed up operation
33 mBuffer[0] = new uint8_t[size];
34 mBuffer[1] = new uint8_t[size];
36 memset(mBuffer[0], 0, size);
37 memset(mBuffer[1], 0, size);
40 LocklessBuffer::~LocklessBuffer()
46 void LocklessBuffer::Write(const uint8_t* src, uint32_t size)
48 DALI_ASSERT_ALWAYS(size <= mSize);
51 BufferState currentState(__sync_fetch_and_or(&mState, WRITING));
52 DALI_ASSERT_DEBUG(!(currentState & WRITING_MASK)); // WRITING bit should never be set when we get here
54 // copy data to current write buffer, negate state to get actual index (recap: R0W1 = 0, R1W0 = 1)
55 const unsigned int index = (currentState & WRITE_BUFFER_MASK);
56 memcpy(mBuffer[index], src, size);
58 // unset WRITING bit, set UPDATED bit
59 BufferState checkState = __sync_val_compare_and_swap(&mState,
60 static_cast<BufferState>(currentState | WRITING),
61 static_cast<BufferState>(index | UPDATED));
63 DALI_ASSERT_DEBUG(checkState & WRITING);
64 (void)checkState; // Avoid unused variable warning
67 const uint8_t* LocklessBuffer::Read()
69 // current state (only to avoid multiple memory reads with volatile variable)
70 BufferState currentState(mState);
71 BufferState currentWriteBuf(static_cast<BufferState>(currentState & WRITE_BUFFER_MASK));
73 if(currentState & UPDATED_MASK)
75 // Try to swap buffers.
76 // This will set mState to 1 if readbuffer 0 was updated, 0 if readbuffer 1 was updated and fail if WRITING is set
77 if(__sync_bool_compare_and_swap(&mState,
78 static_cast<BufferState>(currentWriteBuf | UPDATED),
79 static_cast<BufferState>(!currentWriteBuf)))
82 return mBuffer[currentWriteBuf];
86 // UPDATE bit wasn't set or WRITING bit was set in other thread
87 // swap failed, read from current readbuffer
88 return mBuffer[!currentWriteBuf];
91 uint32_t LocklessBuffer::GetSize() const
93 return static_cast<unsigned int>(mSize);
96 } // namespace Integration