5a7cc58eac6eb949acb4385c43f3c284cbb16c75
[platform/core/uifw/dali-core.git] / dali / integration-api / lockless-buffer.h
1 #ifndef __DALI_INTEGRATION_LOCKLESS_BUFFER_H__
2 #define __DALI_INTEGRATION_LOCKLESS_BUFFER_H__
3
4 /*
5  * Copyright (c) 2018 Samsung Electronics Co., Ltd.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  */
20
21 // EXTERNAL INCLUDES
22
23 // INTERNAL INCLUDES
24 #include <cstring>
25 #include <dali/public-api/common/vector-wrapper.h>
26 #include <dali/public-api/common/dali-common.h>
27
28 #include <atomic>
29
30 namespace Dali
31 {
32
33 namespace Integration
34 {
35
36 /**
37  * The LocklessBuffer class implements double buffering eligible for multi-(two) threaded use,
38  * where it's possible to read from one thread and write from another
39  * without requiring a mutex lock to avoid performance hit.
40  * It's intended to be used for reading bitmap data in render thread
41  * while still possible to write data in another thread.
42  *
43  * Ideally Write() and Read() calls should be alternating, otherwise written data might be thrown away.
44  *
45  * The buffers are swapped in the reading thread, just before reading begins.
46  * In case the other thread is writing at that moment, buffers are not swapped and previously available data is read.
47  * Similarly if Write() is called before a Read() has finished the previous write buffer is overwritten.
48  */
49 class DALI_CORE_API LocklessBuffer
50 {
51
52 public:
53   /**
54    * Constructor.
55    * @param[in] size The size of buffers in bytes.
56    */
57   LocklessBuffer( size_t size );
58
59   /**
60    * Destructor.
61    */
62   ~LocklessBuffer();
63
64   /**
65    * Write data to buffer.
66    * @param[in] src data source
67    * @param[in] size size of data in bytes
68    */
69   void Write( const unsigned char *src, size_t size );
70
71   /**
72    * Try to swap buffers and read data.
73    * @note returned value only valid until Read() is called again or object is destroyed
74    * @return current read buffer contents
75    */
76   const unsigned char* Read();
77
78   /**
79    * @return the buffer size in bytes
80    */
81   unsigned int GetSize() const;
82
83 private:
84   /**
85    * Atomically set state.
86    * We're always writing to one buffer and reading from the other.
87    * Write() sets WRITING bit when started and unsets it when finished.
88    */
89   enum BufferState
90   {
91     R0W1    = 0, ///< Read from buffer 0 write to buffer 1
92     R1W0    = 1, ///< Read from buffer 1 write to buffer 0
93     WRITING = 2, ///< Currently writing to buffer
94     UPDATED = 4, ///< Swapping buffer required; there is new data available
95     WRITE_BUFFER_MASK = 1, ///< indicates which buffer to write to
96     WRITING_MASK      = 2, ///< indicates whether currently writing
97     UPDATED_MASK      = 4  ///< indicates whether new data is available
98   };
99
100 private:
101   LocklessBuffer(); ///< undefined default constructor, need to give size on construction
102   LocklessBuffer( const LocklessBuffer& );            ///< undefined copy constructor
103   LocklessBuffer& operator=( const LocklessBuffer& ); ///< undefined assignment operator
104
105 private:
106   unsigned char* mBuffer[2];     ///< bitmap buffers
107   volatile std::__atomic_base<BufferState> mState;   ///< readbuffer number and whether we're currently writing into writebuffer or not
108   size_t mSize;                  ///< size of buffers
109 };
110
111 } // Internal
112
113 } // Dali
114
115 #endif // __DALI_INTEGRATION_LOCKLESS_H__