Emscripten workarounds and llvm syntax fixes
[platform/core/uifw/dali-core.git] / dali / integration-api / common / lockless-buffer.cpp
1 //
2 // Copyright (c) 2014 Samsung Electronics Co., Ltd.
3 //
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
7 //
8 //     http://floralicense.org/license/
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 // CLASS HEADER
18 #include "lockless-buffer.h"
19
20 // INTERNAL INCLUDES
21 #include <dali/integration-api/debug.h>
22
23 namespace Dali
24 {
25
26 namespace Integration
27 {
28
29 LocklessBuffer::LocklessBuffer( size_t size )
30 : mState( R0W1 ),
31   mSize( size )
32 {
33   // allocate memory to speed up operation
34   mBuffer[0] = new unsigned char[size];
35   mBuffer[1] = new unsigned char[size];
36
37   memset (mBuffer[0], 0, size );
38   memset (mBuffer[1], 0, size );
39 }
40
41 LocklessBuffer::~LocklessBuffer()
42 {
43   delete[] mBuffer[0];
44   delete[] mBuffer[1];
45 }
46
47 void LocklessBuffer::Write( const unsigned char *src, size_t size )
48 {
49   DALI_ASSERT_ALWAYS( size <= mSize );
50
51   // set WRITING bit
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
54
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 );
58
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) );
63
64   DALI_ASSERT_DEBUG( checkState & WRITING );
65   (void)checkState; // Avoid unused variable warning
66 }
67
68 const unsigned char* LocklessBuffer::Read()
69 {
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 ) );
73
74   if( currentState & UPDATED_MASK )
75   {
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) )  )
81     {
82       // swap successful
83       return mBuffer[currentWriteBuf];
84     }
85   }
86
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];
90 }
91
92 unsigned int LocklessBuffer::GetSize() const
93 {
94   return static_cast<unsigned int>(mSize);
95 }
96
97 } // Internal
98
99 } // Dali