Revert "[Tizen] Add codes for Dali Windows Backend"
[platform/core/uifw/dali-core.git] / dali / integration-api / lockless-buffer.cpp
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
22 #include <dali/integration-api/debug.h>
23
24 namespace Dali
25 {
26
27 namespace Integration
28 {
29
30 LocklessBuffer::LocklessBuffer( size_t size )
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
42 LocklessBuffer::~LocklessBuffer()
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